diff --git a/docs/hugo/content/guide/expressions.md b/docs/hugo/content/guide/expressions.md new file mode 100644 index 00000000000..ab205e768f8 --- /dev/null +++ b/docs/hugo/content/guide/expressions.md @@ -0,0 +1,168 @@ +--- +title: CEL Expressions +linktitle: expressions +weight: 1 # This is the default weight if you just want to be ordered alphabetically +--- + +## Expressions in ASO + +ASO offers some support for [Common Expression Language (CEL)](https://github.com/google/cel-spec) expressions. + +Expressions in ASO can be used to build your own Secret or ConfigMap output. This helps to solve problems like: + +- Applications that need connection strings with specific (possibly non-standard) formats. +- Exporting arbitrary fields from a resource for use by other applications. +- Exporting static text alongside dynamic data. + +CEL expressions are currently supported on most resources via the `spec.operatorSpec.configMapExpressions` and +`spec.operatorSpec.secretExpressions` fields, which allow configuring expressions output +to ConfigMaps and Secrets, respectively. + +### Inputs + +Expressions have access to the following inputs: + +| Type | Variable(s) | +|-----------|------------------| +| ConfigMap | `self` | +| Secret | `self`, `secret` | + +`self`: The resource itself. + +{{% alert title="Note" %}} +`self` represents the resource at the version you last applied the resource at. So for example if `v1api20200101` +has a `self.spec.foo` field that has been _removed_ in `v1api20220101`, you can still refer to `self.spec.foo` +in your expressions as long as you're `kubectl apply`-ing the resource with the `v1api20200101` version. + +This also holds for new fields, you can refer to newly added fields _only in the API versions that have those fields_. +{{% /alert %}} + +`secret`: A set of secrets associated with the resource. The specific secrets supported vary by resource type, +but can be found on the `spec.operatorSpec.secrets` type. +For example, [eventhub Namespace](https://azure.github.io/azure-service-operator/reference/eventhub/v1api20211101/#eventhub.azure.com/v1api20211101.NamespaceOperatorSecrets) +supports the following 4 secrets: +- `primaryConnectionString` +- `primaryKey` +- `secondaryConnectionString` +- `secondaryKey` + +### Outputs + +Expressions for `spec.operatorSpec.configMapExpressions` and `spec.operatorSpec.secretExpressions` +must output `string` or `map[string]string` data. Any other expression output type will be rejected. + +### CEL options, language features, and libraries + +Compare with [Kubernetes supported options](https://kubernetes.io/docs/reference/using-api/cel/#cel-options-language-features-and-libraries) + +| Feature | +|------------------------------------------------------------------------------------------------------------------| +| [Standard macros](https://github.com/google/cel-spec/blob/master/doc/langdef.md#macros) | +| [Standard functions](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions) | +| [Default UTC Time Zone](https://pkg.go.dev/github.com/google/cel-go/cel#DefaultUTCTimeZone) | +| [Eagerly Validate Declarations](https://pkg.go.dev/github.com/google/cel-go/cel#EagerlyValidateDeclarations) | +| [Extended String Library, version 3](https://pkg.go.dev/github.com/google/cel-go/ext#Strings) | +| [Optional Types](https://pkg.go.dev/github.com/google/cel-go/cel#OptionalTypes) | +| [Cross Type Numeric comparisons](https://pkg.go.dev/github.com/google/cel-go/cel#CrossTypeNumericComparisons) | + + +### Escaping + +ASO follows the [same escaping rules as Kubernetes](https://kubernetes.io/docs/reference/using-api/cel/#escaping), +except we don't escape CEL keywords. + +While escaping isn't required for most properties, CEL doesn't support the `.`, `-`, or `/` characters in expressions, so +properties whose names contain these characters must be escaped. The escaping rules are: + +| Escape sequence | Property name equivalent | Unescaped example | Escaped example | +|-------------------|----------------------------------------------------------------------------------------------------------------------|-------------------|--------------------------| +| \_\_underscores__ | __ | my__field | my\_\_underscores__field | +| \_\_dot__ | . | my.field | my\_\_dot__field | +| \_\_dash__ | - | my-field | my\_\_dash__field | +| \_\_slash__ | / | my/field | my\_\_slash__field | +| \_\_{keyword}__ | [CEL RESERVED keyword (false, true, in, null)](https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax) | false | \_\_false__ | + +### Examples + +These examples are all written for a simple +[cache.Redis](https://azure.github.io/azure-service-operator/reference/cache/v1api20230801/#cache.azure.com/v1api20230801.Redis). +There's nothing special about Redis it's just used as an example. + +In each of these examples, we start with the given Redis and apply the expression as mentioned in the example itself. + +It might be useful to refer to +the [DestinationExpression](https://pkg.go.dev/github.com/Azure/azure-service-operator/v2/pkg/genruntime/core#DestinationExpression) +documentation to understand what the `name`/`key`/`value` fields are doing in all of these examples. + +For more advanced examples, refer to the +[CEL language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md). + +**Sample Redis:** +```yaml +apiVersion: cache.azure.com/v1api20230801 +kind: Redis +metadata: + name: sampleredis1 + namespace: default + annotations: + foo: bar + baz: qux +spec: + location: westus2 + owner: + name: aso-sample-rg + sku: + family: P + name: Premium + capacity: 1 + enableNonSslPort: false + minimumTlsVersion: "1.2" + redisConfiguration: + maxmemory-delta: "10" + maxmemory-policy: allkeys-lru + redisVersion: "6" + zones: + - "1" + - "2" + - "3" +``` + +{{% alert title="Note" %}} +Just to keep it simple, the sample YAML doesn't include status. Real resources have status, and you can build your +CEL expressions with `self.status` in addition to `self.spec` or `self.metadata`. +{{% /alert %}} + +#### A full example + +Expression snippet: +```yaml +spec: + operatorSpec: + configMapExpressions: + - name: my-configmap + key: location + value: self.spec.location +``` + +Output (ConfigMap): +```yaml +metadata: + name: my-configmap +data: + location: westus2 +``` + +From here on, we'll elide the supporting YAML of the above example and just focus on the CEL expression input (`value`) +and the resulting output, still based on the example `Redis` above. + +| Description | Expression | Result | +|--------------------|--------------------------------------------------------|---------------------------------------------------------------------------------------------------------| +| Hardcoded string | `"helloworld"` | `helloworld` | +| Formatted string | `"%s:%d".format([self.spec.location, 7])` | `westus2:7` | +| String math | `self.metadata.namespace + ":" + self.metadata.name` | `default:sampleredis1` | +| Int output (error) | `self.spec.sku.capacity` | Error, expression "self.spec.sku.capacity" must return one of [string,map(string, string)], but was int | +| Coerce to string | `string(self.spec.sku.capacity)` | `1` | +| Map output | `self.metadata.annotations` | `{"foo": "bar", "baz": "qux"}` | +| Array macro | `self.spec.zones.filter(a, int(a) % 2 == 0).join("-")` | `2-4` | +| Select array item | `self.spec.zones[0]` | `1` | +| Select map item | `self.metadata.annotations["foo"]` | `bar` | diff --git a/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen.go b/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen.go index 365b1fcf322..be9567f7b8b 100644 --- a/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen.go +++ b/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *PrometheusRuleGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrometheusRuleGroup resource func (group *PrometheusRuleGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &PrometheusRuleGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *PrometheusRuleGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrometheusRuleGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *PrometheusRuleGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrometheusRuleGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *PrometheusRuleGroup) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (group *PrometheusRuleGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *PrometheusRuleGroup) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *PrometheusRuleGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *PrometheusRuleGroup) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *PrometheusRuleGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *PrometheusRuleGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrometheusRuleGroup) @@ -353,6 +398,10 @@ type PrometheusRuleGroup_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrometheusRuleGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -497,6 +546,8 @@ func (group *PrometheusRuleGroup_Spec) PopulateFromARM(owner genruntime.Arbitrar group.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -606,6 +657,18 @@ func (group *PrometheusRuleGroup_Spec) AssignProperties_From_PrometheusRuleGroup // Location group.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrometheusRuleGroupOperatorSpec + err := operatorSpec.AssignProperties_From_PrometheusRuleGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrometheusRuleGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -680,6 +743,18 @@ func (group *PrometheusRuleGroup_Spec) AssignProperties_To_PrometheusRuleGroup_S // Location destination.Location = genruntime.ClonePointerToString(group.Location) + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.PrometheusRuleGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_PrometheusRuleGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrometheusRuleGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -1848,6 +1923,110 @@ func (rule *PrometheusRule_STATUS) AssignProperties_To_PrometheusRule_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrometheusRuleGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrometheusRuleGroupOperatorSpec populates our PrometheusRuleGroupOperatorSpec from the provided source PrometheusRuleGroupOperatorSpec +func (operator *PrometheusRuleGroupOperatorSpec) AssignProperties_From_PrometheusRuleGroupOperatorSpec(source *storage.PrometheusRuleGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrometheusRuleGroupOperatorSpec populates the provided destination PrometheusRuleGroupOperatorSpec from our PrometheusRuleGroupOperatorSpec +func (operator *PrometheusRuleGroupOperatorSpec) AssignProperties_To_PrometheusRuleGroupOperatorSpec(destination *storage.PrometheusRuleGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen_test.go b/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen_test.go index 459d7aea60c..c2a14c9afd4 100644 --- a/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen_test.go +++ b/v2/api/alertsmanagement/v1api20230301/prometheus_rule_group_types_gen_test.go @@ -504,6 +504,103 @@ func AddIndependentPropertyGeneratorsForPrometheusRuleGroupAction_STATUS(gens ma gen.AlphaString()) } +func Test_PrometheusRuleGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrometheusRuleGroupOperatorSpec to PrometheusRuleGroupOperatorSpec via AssignProperties_To_PrometheusRuleGroupOperatorSpec & AssignProperties_From_PrometheusRuleGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrometheusRuleGroupOperatorSpec, PrometheusRuleGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrometheusRuleGroupOperatorSpec tests if a specific instance of PrometheusRuleGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrometheusRuleGroupOperatorSpec(subject PrometheusRuleGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrometheusRuleGroupOperatorSpec + err := copied.AssignProperties_To_PrometheusRuleGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrometheusRuleGroupOperatorSpec + err = actual.AssignProperties_From_PrometheusRuleGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrometheusRuleGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrometheusRuleGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec, PrometheusRuleGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec runs a test to see if a specific instance of PrometheusRuleGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec(subject PrometheusRuleGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrometheusRuleGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrometheusRuleGroupOperatorSpec instances for property testing - lazily instantiated by +// PrometheusRuleGroupOperatorSpecGenerator() +var prometheusRuleGroupOperatorSpecGenerator gopter.Gen + +// PrometheusRuleGroupOperatorSpecGenerator returns a generator of PrometheusRuleGroupOperatorSpec instances for property testing. +func PrometheusRuleGroupOperatorSpecGenerator() gopter.Gen { + if prometheusRuleGroupOperatorSpecGenerator != nil { + return prometheusRuleGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + prometheusRuleGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrometheusRuleGroupOperatorSpec{}), generators) + + return prometheusRuleGroupOperatorSpecGenerator +} + func Test_PrometheusRuleGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -755,6 +852,7 @@ func AddIndependentPropertyGeneratorsForPrometheusRuleGroup_Spec(gens map[string // AddRelatedPropertyGeneratorsForPrometheusRuleGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrometheusRuleGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrometheusRuleGroupOperatorSpecGenerator()) gens["Rules"] = gen.SliceOf(PrometheusRuleGenerator()) } diff --git a/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen.go b/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen.go index 2383850362d..cef9c13cca1 100644 --- a/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen.go +++ b/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *PrometheusRuleGroup) SetConditions(conditions conditions.Conditions group.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrometheusRuleGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *PrometheusRuleGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrometheusRuleGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *PrometheusRuleGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrometheusRuleGroup{} // AzureName returns the Azure name of the resource @@ -148,13 +171,14 @@ const APIVersion_Value = APIVersion("2023-03-01") type PrometheusRuleGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClusterName *string `json:"clusterName,omitempty"` - Description *string `json:"description,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Interval *string `json:"interval,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClusterName *string `json:"clusterName,omitempty"` + Description *string `json:"description,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Interval *string `json:"interval,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *PrometheusRuleGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -257,6 +281,14 @@ type PrometheusRule_STATUS struct { Severity *int `json:"severity,omitempty"` } +// Storage version of v1api20230301.PrometheusRuleGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrometheusRuleGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230301.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen_test.go b/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen_test.go index e55f799866d..f6f1f0cc2cc 100644 --- a/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen_test.go +++ b/v2/api/alertsmanagement/v1api20230301/storage/prometheus_rule_group_types_gen_test.go @@ -292,6 +292,61 @@ func AddIndependentPropertyGeneratorsForPrometheusRuleGroupAction_STATUS(gens ma gen.AlphaString()) } +func Test_PrometheusRuleGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrometheusRuleGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec, PrometheusRuleGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec runs a test to see if a specific instance of PrometheusRuleGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrometheusRuleGroupOperatorSpec(subject PrometheusRuleGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrometheusRuleGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrometheusRuleGroupOperatorSpec instances for property testing - lazily instantiated by +// PrometheusRuleGroupOperatorSpecGenerator() +var prometheusRuleGroupOperatorSpecGenerator gopter.Gen + +// PrometheusRuleGroupOperatorSpecGenerator returns a generator of PrometheusRuleGroupOperatorSpec instances for property testing. +func PrometheusRuleGroupOperatorSpecGenerator() gopter.Gen { + if prometheusRuleGroupOperatorSpecGenerator != nil { + return prometheusRuleGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + prometheusRuleGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrometheusRuleGroupOperatorSpec{}), generators) + + return prometheusRuleGroupOperatorSpecGenerator +} + func Test_PrometheusRuleGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -460,6 +515,7 @@ func AddIndependentPropertyGeneratorsForPrometheusRuleGroup_Spec(gens map[string // AddRelatedPropertyGeneratorsForPrometheusRuleGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrometheusRuleGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrometheusRuleGroupOperatorSpecGenerator()) gens["Rules"] = gen.SliceOf(PrometheusRuleGenerator()) } diff --git a/v2/api/alertsmanagement/v1api20230301/storage/structure.txt b/v2/api/alertsmanagement/v1api20230301/storage/structure.txt index fc7124a2fbf..609a6447549 100644 --- a/v2/api/alertsmanagement/v1api20230301/storage/structure.txt +++ b/v2/api/alertsmanagement/v1api20230301/storage/structure.txt @@ -5,13 +5,17 @@ APIVersion: Enum (1 value) └── "2023-03-01" PrometheusRuleGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AzureName: string │ ├── ClusterName: *string │ ├── Description: *string │ ├── Enabled: *bool │ ├── Interval: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/alertsmanagement/v1api20230301/storage/zz_generated.deepcopy.go b/v2/api/alertsmanagement/v1api20230301/storage/zz_generated.deepcopy.go index 1f14e43f931..27df6f5ceb9 100644 --- a/v2/api/alertsmanagement/v1api20230301/storage/zz_generated.deepcopy.go +++ b/v2/api/alertsmanagement/v1api20230301/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -220,6 +221,50 @@ func (in *PrometheusRuleGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusRuleGroupOperatorSpec) DeepCopyInto(out *PrometheusRuleGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusRuleGroupOperatorSpec. +func (in *PrometheusRuleGroupOperatorSpec) DeepCopy() *PrometheusRuleGroupOperatorSpec { + if in == nil { + return nil + } + out := new(PrometheusRuleGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrometheusRuleGroup_STATUS) DeepCopyInto(out *PrometheusRuleGroup_STATUS) { *out = *in @@ -341,6 +386,11 @@ func (in *PrometheusRuleGroup_Spec) DeepCopyInto(out *PrometheusRuleGroup_Spec) *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrometheusRuleGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/alertsmanagement/v1api20230301/structure.txt b/v2/api/alertsmanagement/v1api20230301/structure.txt index e417a9df873..4671476cab5 100644 --- a/v2/api/alertsmanagement/v1api20230301/structure.txt +++ b/v2/api/alertsmanagement/v1api20230301/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-03-01" PrometheusRuleGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[^:@/#{}%&+*<>?]+$" │ ├── ClusterName: *string @@ -13,6 +13,9 @@ PrometheusRuleGroup: Resource │ ├── Enabled: *bool │ ├── Interval: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Rules: Object (10 properties)[] │ │ ├── Actions: Object (2 properties)[] diff --git a/v2/api/alertsmanagement/v1api20230301/zz_generated.deepcopy.go b/v2/api/alertsmanagement/v1api20230301/zz_generated.deepcopy.go index 84483029fa0..26668ffd80c 100644 --- a/v2/api/alertsmanagement/v1api20230301/zz_generated.deepcopy.go +++ b/v2/api/alertsmanagement/v1api20230301/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230301 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -199,6 +200,43 @@ func (in *PrometheusRuleGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusRuleGroupOperatorSpec) DeepCopyInto(out *PrometheusRuleGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusRuleGroupOperatorSpec. +func (in *PrometheusRuleGroupOperatorSpec) DeepCopy() *PrometheusRuleGroupOperatorSpec { + if in == nil { + return nil + } + out := new(PrometheusRuleGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrometheusRuleGroup_STATUS) DeepCopyInto(out *PrometheusRuleGroup_STATUS) { *out = *in @@ -313,6 +351,11 @@ func (in *PrometheusRuleGroup_Spec) DeepCopyInto(out *PrometheusRuleGroup_Spec) *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrometheusRuleGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/apimanagement/v1api20220801/api_types_gen.go b/v2/api/apimanagement/v1api20220801/api_types_gen.go index 31a1cc539c0..a70105249c9 100644 --- a/v2/api/apimanagement/v1api20220801/api_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/api_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -89,6 +92,26 @@ func (api *Api) defaultAzureName() { // defaultImpl applies the code generated defaults to the Api resource func (api *Api) defaultImpl() { api.defaultAzureName() } +var _ configmaps.Exporter = &Api{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (api *Api) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Api{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (api *Api) SecretDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Api{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (api *Api) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (api *Api) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){api.validateResourceReferences, api.validateOwnerReference} + return []func() (admission.Warnings, error){api.validateResourceReferences, api.validateOwnerReference, api.validateSecretDestinations, api.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -226,7 +249,21 @@ func (api *Api) updateValidations() []func(old runtime.Object) (admission.Warnin func(old runtime.Object) (admission.Warnings, error) { return api.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return api.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return api.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (api *Api) validateConfigMapDestinations() (admission.Warnings, error) { + if api.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(api, nil, api.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -243,6 +280,14 @@ func (api *Api) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (api *Api) validateSecretDestinations() (admission.Warnings, error) { + if api.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(api, nil, api.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (api *Api) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Api) @@ -385,6 +430,10 @@ type Api_Spec struct { // License: License information for the API. License *ApiLicenseInformation `json:"license,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApiOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -775,6 +824,8 @@ func (api *Api_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, a } } + // no assignment for property "OperatorSpec" + // Set property "Owner": api.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1073,6 +1124,18 @@ func (api *Api_Spec) AssignProperties_From_Api_Spec(source *storage.Api_Spec) er api.License = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiOperatorSpec + err := operatorSpec.AssignProperties_From_ApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiOperatorSpec() to populate field OperatorSpec") + } + api.OperatorSpec = &operatorSpec + } else { + api.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1309,6 +1372,18 @@ func (api *Api_Spec) AssignProperties_To_Api_Spec(destination *storage.Api_Spec) destination.License = nil } + // OperatorSpec + if api.OperatorSpec != nil { + var operatorSpec storage.ApiOperatorSpec + err := api.OperatorSpec.AssignProperties_To_ApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = api.OriginalVersion() @@ -2958,6 +3033,110 @@ func (information *ApiLicenseInformation_STATUS) AssignProperties_To_ApiLicenseI return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiOperatorSpec populates our ApiOperatorSpec from the provided source ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_From_ApiOperatorSpec(source *storage.ApiOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApiOperatorSpec populates the provided destination ApiOperatorSpec from our ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_To_ApiOperatorSpec(destination *storage.ApiOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An API Version Set contains the common configuration for a set of API Versions relating type ApiVersionSetContractDetails struct { // Description: Description of API Version Set. diff --git a/v2/api/apimanagement/v1api20220801/api_types_gen_test.go b/v2/api/apimanagement/v1api20220801/api_types_gen_test.go index 8b030d51f68..f7c69ff1fd2 100644 --- a/v2/api/apimanagement/v1api20220801/api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/api_types_gen_test.go @@ -686,6 +686,102 @@ func AddIndependentPropertyGeneratorsForApiLicenseInformation_STATUS(gens map[st gens["Url"] = gen.PtrOf(gen.AlphaString()) } +func Test_ApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiOperatorSpec to ApiOperatorSpec via AssignProperties_To_ApiOperatorSpec & AssignProperties_From_ApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiOperatorSpec tests if a specific instance of ApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApiOperatorSpec + err := copied.AssignProperties_To_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiOperatorSpec + err = actual.AssignProperties_From_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiOperatorSpec runs a test to see if a specific instance of ApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiOperatorSpec instances for property testing - lazily instantiated by ApiOperatorSpecGenerator() +var apiOperatorSpecGenerator gopter.Gen + +// ApiOperatorSpecGenerator returns a generator of ApiOperatorSpec instances for property testing. +func ApiOperatorSpecGenerator() gopter.Gen { + if apiOperatorSpecGenerator != nil { + return apiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiOperatorSpec{}), generators) + + return apiOperatorSpecGenerator +} + func Test_ApiVersionSetContractDetails_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1204,6 +1300,7 @@ func AddRelatedPropertyGeneratorsForApi_Spec(gens map[string]gopter.Gen) { gens["AuthenticationSettings"] = gen.PtrOf(AuthenticationSettingsContractGenerator()) gens["Contact"] = gen.PtrOf(ApiContactInformationGenerator()) gens["License"] = gen.PtrOf(ApiLicenseInformationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApiOperatorSpecGenerator()) gens["SubscriptionKeyParameterNames"] = gen.PtrOf(SubscriptionKeyParameterNamesContractGenerator()) gens["WsdlSelector"] = gen.PtrOf(ApiCreateOrUpdateProperties_WsdlSelectorGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/api_version_set_types_gen.go b/v2/api/apimanagement/v1api20220801/api_version_set_types_gen.go index ac563039472..0278ab39bfe 100644 --- a/v2/api/apimanagement/v1api20220801/api_version_set_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/api_version_set_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (versionSet *ApiVersionSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the ApiVersionSet resource func (versionSet *ApiVersionSet) defaultImpl() { versionSet.defaultAzureName() } +var _ configmaps.Exporter = &ApiVersionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (versionSet *ApiVersionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApiVersionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (versionSet *ApiVersionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ApiVersionSet{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (versionSet *ApiVersionSet) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (versionSet *ApiVersionSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){versionSet.validateResourceReferences, versionSet.validateOwnerReference} + return []func() (admission.Warnings, error){versionSet.validateResourceReferences, versionSet.validateOwnerReference, versionSet.validateSecretDestinations, versionSet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,9 +251,23 @@ func (versionSet *ApiVersionSet) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return versionSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return versionSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return versionSet.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (versionSet *ApiVersionSet) validateConfigMapDestinations() (admission.Warnings, error) { + if versionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(versionSet, nil, versionSet.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (versionSet *ApiVersionSet) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(versionSet) @@ -245,6 +282,14 @@ func (versionSet *ApiVersionSet) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (versionSet *ApiVersionSet) validateSecretDestinations() (admission.Warnings, error) { + if versionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(versionSet, nil, versionSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (versionSet *ApiVersionSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ApiVersionSet) @@ -343,6 +388,10 @@ type ApiVersionSet_Spec struct { // DisplayName: Name of API Version Set DisplayName *string `json:"displayName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApiVersionSetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -442,6 +491,8 @@ func (versionSet *ApiVersionSet_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": versionSet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -548,6 +599,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_From_ApiVersionSet_Spec(s versionSet.DisplayName = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiVersionSetOperatorSpec + err := operatorSpec.AssignProperties_From_ApiVersionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + versionSet.OperatorSpec = &operatorSpec + } else { + versionSet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -604,6 +667,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_To_ApiVersionSet_Spec(des destination.DisplayName = nil } + // OperatorSpec + if versionSet.OperatorSpec != nil { + var operatorSpec storage.ApiVersionSetOperatorSpec + err := versionSet.OperatorSpec.AssignProperties_To_ApiVersionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = versionSet.OriginalVersion() @@ -986,6 +1061,110 @@ var apiVersionSetContractProperties_VersioningScheme_STATUS_Values = map[string] "segment": ApiVersionSetContractProperties_VersioningScheme_STATUS_Segment, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiVersionSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiVersionSetOperatorSpec populates our ApiVersionSetOperatorSpec from the provided source ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_From_ApiVersionSetOperatorSpec(source *storage.ApiVersionSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApiVersionSetOperatorSpec populates the provided destination ApiVersionSetOperatorSpec from our ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_To_ApiVersionSetOperatorSpec(destination *storage.ApiVersionSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ApiVersionSet{}, &ApiVersionSetList{}) } diff --git a/v2/api/apimanagement/v1api20220801/api_version_set_types_gen_test.go b/v2/api/apimanagement/v1api20220801/api_version_set_types_gen_test.go index 696bc080108..ce9123ee101 100644 --- a/v2/api/apimanagement/v1api20220801/api_version_set_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/api_version_set_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForApiVersionSet(gens map[string]gopter.Gen) { gens["Status"] = ApiVersionSet_STATUSGenerator() } +func Test_ApiVersionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiVersionSetOperatorSpec to ApiVersionSetOperatorSpec via AssignProperties_To_ApiVersionSetOperatorSpec & AssignProperties_From_ApiVersionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiVersionSetOperatorSpec tests if a specific instance of ApiVersionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApiVersionSetOperatorSpec + err := copied.AssignProperties_To_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiVersionSetOperatorSpec + err = actual.AssignProperties_From_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiVersionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiVersionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiVersionSetOperatorSpec runs a test to see if a specific instance of ApiVersionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiVersionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiVersionSetOperatorSpec instances for property testing - lazily instantiated by +// ApiVersionSetOperatorSpecGenerator() +var apiVersionSetOperatorSpecGenerator gopter.Gen + +// ApiVersionSetOperatorSpecGenerator returns a generator of ApiVersionSetOperatorSpec instances for property testing. +func ApiVersionSetOperatorSpecGenerator() gopter.Gen { + if apiVersionSetOperatorSpecGenerator != nil { + return apiVersionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiVersionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSetOperatorSpec{}), generators) + + return apiVersionSetOperatorSpecGenerator +} + func Test_ApiVersionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForApiVersionSet_Spec(subject ApiVersionSet_Spec) s var apiVersionSet_SpecGenerator gopter.Gen // ApiVersionSet_SpecGenerator returns a generator of ApiVersionSet_Spec instances for property testing. +// We first initialize apiVersionSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApiVersionSet_SpecGenerator() gopter.Gen { if apiVersionSet_SpecGenerator != nil { return apiVersionSet_SpecGenerator @@ -368,6 +468,12 @@ func ApiVersionSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) + AddRelatedPropertyGeneratorsForApiVersionSet_Spec(generators) + apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + return apiVersionSet_SpecGenerator } @@ -380,3 +486,8 @@ func AddIndependentPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopte gens["VersionQueryName"] = gen.PtrOf(gen.AlphaString()) gens["VersioningScheme"] = gen.PtrOf(gen.OneConstOf(ApiVersionSetContractProperties_VersioningScheme_Header, ApiVersionSetContractProperties_VersioningScheme_Query, ApiVersionSetContractProperties_VersioningScheme_Segment)) } + +// AddRelatedPropertyGeneratorsForApiVersionSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApiVersionSetOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen.go b/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen.go index 3631cd49e65..0e49932e006 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (provider *AuthorizationProvider) defaultAzureName() { // defaultImpl applies the code generated defaults to the AuthorizationProvider resource func (provider *AuthorizationProvider) defaultImpl() { provider.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvider{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (provider *AuthorizationProvider) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvider{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (provider *AuthorizationProvider) SecretDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AuthorizationProvider{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (provider *AuthorizationProvider) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (provider *AuthorizationProvider) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){provider.validateResourceReferences, provider.validateOwnerReference} + return []func() (admission.Warnings, error){provider.validateResourceReferences, provider.validateOwnerReference, provider.validateSecretDestinations, provider.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (provider *AuthorizationProvider) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return provider.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return provider.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return provider.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (provider *AuthorizationProvider) validateConfigMapDestinations() (admission.Warnings, error) { + if provider.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(provider, nil, provider.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (provider *AuthorizationProvider) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (provider *AuthorizationProvider) validateSecretDestinations() (admission.Warnings, error) { + if provider.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(provider, nil, provider.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (provider *AuthorizationProvider) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvider) @@ -344,6 +389,10 @@ type AuthorizationProvider_Spec struct { // Oauth2: OAuth2 settings Oauth2 *AuthorizationProviderOAuth2Settings `json:"oauth2,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProviderOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -435,6 +484,8 @@ func (provider *AuthorizationProvider_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": provider.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -524,6 +575,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_From_AuthorizationP provider.Oauth2 = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProviderOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProviderOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + provider.OperatorSpec = &operatorSpec + } else { + provider.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -567,6 +630,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_To_AuthorizationPro destination.Oauth2 = nil } + // OperatorSpec + if provider.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProviderOperatorSpec + err := provider.OperatorSpec.AssignProperties_To_AuthorizationProviderOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = provider.OriginalVersion() @@ -1097,6 +1172,110 @@ func (settings *AuthorizationProviderOAuth2Settings_STATUS) AssignProperties_To_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProviderOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProviderOperatorSpec populates our AuthorizationProviderOperatorSpec from the provided source AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_From_AuthorizationProviderOperatorSpec(source *storage.AuthorizationProviderOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProviderOperatorSpec populates the provided destination AuthorizationProviderOperatorSpec from our AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_To_AuthorizationProviderOperatorSpec(destination *storage.AuthorizationProviderOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Authorization Provider oauth2 grant types settings type AuthorizationProviderOAuth2GrantTypes struct { // AuthorizationCode: OAuth2 authorization code grant parameters diff --git a/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen_test.go b/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen_test.go index 3f4f5986db9..d19c6279a1d 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/authorization_provider_types_gen_test.go @@ -604,6 +604,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProviderOAuth2Settings_STATUS(g gens["GrantTypes"] = gen.PtrOf(AuthorizationProviderOAuth2GrantTypes_STATUSGenerator()) } +func Test_AuthorizationProviderOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProviderOperatorSpec to AuthorizationProviderOperatorSpec via AssignProperties_To_AuthorizationProviderOperatorSpec & AssignProperties_From_AuthorizationProviderOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec tests if a specific instance of AuthorizationProviderOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProviderOperatorSpec + err := copied.AssignProperties_To_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProviderOperatorSpec + err = actual.AssignProperties_From_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProviderOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProviderOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProviderOperatorSpec runs a test to see if a specific instance of AuthorizationProviderOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProviderOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProviderOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProviderOperatorSpecGenerator() +var authorizationProviderOperatorSpecGenerator gopter.Gen + +// AuthorizationProviderOperatorSpecGenerator returns a generator of AuthorizationProviderOperatorSpec instances for property testing. +func AuthorizationProviderOperatorSpecGenerator() gopter.Gen { + if authorizationProviderOperatorSpecGenerator != nil { + return authorizationProviderOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProviderOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProviderOperatorSpec{}), generators) + + return authorizationProviderOperatorSpecGenerator +} + func Test_AuthorizationProvider_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -842,4 +939,5 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvider_Spec(gens map[stri // AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec(gens map[string]gopter.Gen) { gens["Oauth2"] = gen.PtrOf(AuthorizationProviderOAuth2SettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProviderOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen.go b/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen.go index 4dbdba8ec44..f9489c7bdc1 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -93,6 +96,26 @@ func (authorization *AuthorizationProvidersAuthorization) defaultImpl() { authorization.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorization{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authorization *AuthorizationProvidersAuthorization) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorization{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authorization *AuthorizationProvidersAuthorization) SecretDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AuthorizationProvidersAuthorization{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +234,7 @@ func (authorization *AuthorizationProvidersAuthorization) ValidateUpdate(old run // createValidations validates the creation of the resource func (authorization *AuthorizationProvidersAuthorization) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){authorization.validateResourceReferences, authorization.validateOwnerReference} + return []func() (admission.Warnings, error){authorization.validateResourceReferences, authorization.validateOwnerReference, authorization.validateSecretDestinations, authorization.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (authorization *AuthorizationProvidersAuthorization) updateValidations() [] func(old runtime.Object) (admission.Warnings, error) { return authorization.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return authorization.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return authorization.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (authorization *AuthorizationProvidersAuthorization) validateConfigMapDestinations() (admission.Warnings, error) { + if authorization.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(authorization, nil, authorization.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (authorization *AuthorizationProvidersAuthorization) validateResourceRefere return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (authorization *AuthorizationProvidersAuthorization) validateSecretDestinations() (admission.Warnings, error) { + if authorization.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(authorization, nil, authorization.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (authorization *AuthorizationProvidersAuthorization) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvidersAuthorization) @@ -341,6 +386,10 @@ type AuthorizationProvidersAuthorization_Spec struct { // Oauth2GrantType: OAuth2 grant type options Oauth2GrantType *AuthorizationContractProperties_Oauth2GrantType `json:"oauth2grantType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProvidersAuthorizationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -430,6 +479,8 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) PopulateFromARM(o } } + // no assignment for property "OperatorSpec" + // Set property "Owner": authorization.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -516,6 +567,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ authorization.Oauth2GrantType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + authorization.OperatorSpec = &operatorSpec + } else { + authorization.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -560,6 +623,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ destination.Oauth2GrantType = nil } + // OperatorSpec + if authorization.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationOperatorSpec + err := authorization.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = authorization.OriginalVersion() @@ -1034,6 +1109,110 @@ func (error *AuthorizationError_STATUS) AssignProperties_To_AuthorizationError_S return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec populates our AuthorizationProvidersAuthorizationOperatorSpec from the provided source AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationOperatorSpec from our AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorization{}, &AuthorizationProvidersAuthorizationList{}) } diff --git a/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen_test.go b/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen_test.go index 67265a6c661..f65771c3690 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/authorization_providers_authorization_types_gen_test.go @@ -269,6 +269,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization(gens map gens["Status"] = AuthorizationProvidersAuthorization_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationOperatorSpec to AuthorizationProvidersAuthorizationOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProvidersAuthorizationOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProvidersAuthorizationOperatorSpecGenerator() +var authorizationProvidersAuthorizationOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorization_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -480,6 +577,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorization_Spec(subject var authorizationProvidersAuthorization_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorization_SpecGenerator returns a generator of AuthorizationProvidersAuthorization_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorization_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorization_SpecGenerator != nil { return authorizationProvidersAuthorization_SpecGenerator @@ -489,6 +589,12 @@ func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + return authorizationProvidersAuthorization_SpecGenerator } @@ -498,3 +604,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec gens["AzureName"] = gen.AlphaString() gens["Oauth2GrantType"] = gen.PtrOf(gen.OneConstOf(AuthorizationContractProperties_Oauth2GrantType_AuthorizationCode, AuthorizationContractProperties_Oauth2GrantType_ClientCredentials)) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen.go b/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen.go index c74f4b1f3ee..62bd4b5f081 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -94,6 +96,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AuthorizationProvidersAuthorizationsAccessPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -212,7 +234,7 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ValidateUpdate(o // createValidations validates the creation of the resource func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations, policy.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -230,12 +252,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) updateValidation func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return policy.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&policy.Spec) @@ -259,6 +295,14 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateResource return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvidersAuthorizationsAccessPolicy) @@ -354,6 +398,10 @@ type AuthorizationProvidersAuthorizationsAccessPolicy_Spec struct { // ObjectIdFromConfig: The Object Id ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -439,6 +487,8 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) PopulateFro // no assignment for property "ObjectIdFromConfig" + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -527,6 +577,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope policy.ObjectIdFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -569,6 +631,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope destination.ObjectIdFromConfig = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -811,6 +885,110 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) AssignPro return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from the provided source AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorizationsAccessPolicy{}, &AuthorizationProvidersAuthorizationsAccessPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen_test.go index 5a0a44a782d..f26d29740ef 100644 --- a/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/authorization_providers_authorizations_access_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPo gens["Status"] = AuthorizationProvidersAuthorizationsAccessPolicy_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec to AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing - lazily +// instantiated by AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() +var authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorizationsAccessPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicy var authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicy_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator != nil { return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator @@ -367,6 +467,12 @@ func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAcce gens["ObjectId"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/backend_types_gen.go b/v2/api/apimanagement/v1api20220801/backend_types_gen.go index 2f51f9694cf..f607eaface2 100644 --- a/v2/api/apimanagement/v1api20220801/backend_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/backend_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (backend *Backend) defaultAzureName() { // defaultImpl applies the code generated defaults to the Backend resource func (backend *Backend) defaultImpl() { backend.defaultAzureName() } +var _ configmaps.Exporter = &Backend{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (backend *Backend) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Backend{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (backend *Backend) SecretDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Backend{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (backend *Backend) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (backend *Backend) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){backend.validateResourceReferences, backend.validateOwnerReference} + return []func() (admission.Warnings, error){backend.validateResourceReferences, backend.validateOwnerReference, backend.validateSecretDestinations, backend.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (backend *Backend) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return backend.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return backend.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return backend.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (backend *Backend) validateConfigMapDestinations() (admission.Warnings, error) { + if backend.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(backend, nil, backend.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (backend *Backend) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (backend *Backend) validateSecretDestinations() (admission.Warnings, error) { + if backend.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(backend, nil, backend.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (backend *Backend) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Backend) @@ -341,6 +386,10 @@ type Backend_Spec struct { // Description: Backend Description. Description *string `json:"description,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BackendOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -499,6 +548,8 @@ func (backend *Backend_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": backend.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -658,6 +709,18 @@ func (backend *Backend_Spec) AssignProperties_From_Backend_Spec(source *storage. backend.Description = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackendOperatorSpec + err := operatorSpec.AssignProperties_From_BackendOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackendOperatorSpec() to populate field OperatorSpec") + } + backend.OperatorSpec = &operatorSpec + } else { + backend.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -767,6 +830,18 @@ func (backend *Backend_Spec) AssignProperties_To_Backend_Spec(destination *stora destination.Description = nil } + // OperatorSpec + if backend.OperatorSpec != nil { + var operatorSpec storage.BackendOperatorSpec + err := backend.OperatorSpec.AssignProperties_To_BackendOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackendOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = backend.OriginalVersion() @@ -1955,6 +2030,110 @@ func (contract *BackendCredentialsContract_STATUS) AssignProperties_To_BackendCr return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackendOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackendOperatorSpec populates our BackendOperatorSpec from the provided source BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_From_BackendOperatorSpec(source *storage.BackendOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BackendOperatorSpec populates the provided destination BackendOperatorSpec from our BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_To_BackendOperatorSpec(destination *storage.BackendOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties specific to the Backend Type. type BackendProperties struct { // ServiceFabricCluster: Backend Service Fabric Cluster Properties diff --git a/v2/api/apimanagement/v1api20220801/backend_types_gen_test.go b/v2/api/apimanagement/v1api20220801/backend_types_gen_test.go index 4da5d1d46d7..25fe373af70 100644 --- a/v2/api/apimanagement/v1api20220801/backend_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/backend_types_gen_test.go @@ -620,6 +620,103 @@ func AddRelatedPropertyGeneratorsForBackendCredentialsContract_STATUS(gens map[s gens["Authorization"] = gen.PtrOf(BackendAuthorizationHeaderCredentials_STATUSGenerator()) } +func Test_BackendOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackendOperatorSpec to BackendOperatorSpec via AssignProperties_To_BackendOperatorSpec & AssignProperties_From_BackendOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackendOperatorSpec tests if a specific instance of BackendOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BackendOperatorSpec + err := copied.AssignProperties_To_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackendOperatorSpec + err = actual.AssignProperties_From_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackendOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackendOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackendOperatorSpec runs a test to see if a specific instance of BackendOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackendOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackendOperatorSpec instances for property testing - lazily instantiated by +// BackendOperatorSpecGenerator() +var backendOperatorSpecGenerator gopter.Gen + +// BackendOperatorSpecGenerator returns a generator of BackendOperatorSpec instances for property testing. +func BackendOperatorSpecGenerator() gopter.Gen { + if backendOperatorSpecGenerator != nil { + return backendOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backendOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackendOperatorSpec{}), generators) + + return backendOperatorSpecGenerator +} + func Test_BackendProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1727,6 +1824,7 @@ func AddIndependentPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForBackend_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) { gens["Credentials"] = gen.PtrOf(BackendCredentialsContractGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BackendOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BackendPropertiesGenerator()) gens["Proxy"] = gen.PtrOf(BackendProxyContractGenerator()) gens["Tls"] = gen.PtrOf(BackendTlsPropertiesGenerator()) diff --git a/v2/api/apimanagement/v1api20220801/named_value_types_gen.go b/v2/api/apimanagement/v1api20220801/named_value_types_gen.go index 872a6c93024..f77f66ab7be 100644 --- a/v2/api/apimanagement/v1api20220801/named_value_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/named_value_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (value *NamedValue) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamedValue resource func (value *NamedValue) defaultImpl() { value.defaultAzureName() } +var _ configmaps.Exporter = &NamedValue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (value *NamedValue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamedValue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (value *NamedValue) SecretDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamedValue{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +233,7 @@ func (value *NamedValue) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (value *NamedValue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){value.validateResourceReferences, value.validateOwnerReference, value.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){value.validateResourceReferences, value.validateOwnerReference, value.validateSecretDestinations, value.validateConfigMapDestinations, value.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -229,12 +251,26 @@ func (value *NamedValue) updateValidations() []func(old runtime.Object) (admissi func(old runtime.Object) (admission.Warnings, error) { return value.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return value.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return value.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return value.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (value *NamedValue) validateConfigMapDestinations() (admission.Warnings, error) { + if value.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(value, nil, value.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (value *NamedValue) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&value.Spec) @@ -258,6 +294,14 @@ func (value *NamedValue) validateResourceReferences() (admission.Warnings, error return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (value *NamedValue) validateSecretDestinations() (admission.Warnings, error) { + if value.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(value, nil, value.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (value *NamedValue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamedValue) @@ -356,6 +400,10 @@ type NamedValue_Spec struct { // KeyVault: KeyVault location details of the namedValue. KeyVault *KeyVaultContractCreateProperties `json:"keyVault,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamedValueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -459,6 +507,8 @@ func (value *NamedValue_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRef } } + // no assignment for property "OperatorSpec" + // Set property "Owner": value.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -571,6 +621,18 @@ func (value *NamedValue_Spec) AssignProperties_From_NamedValue_Spec(source *stor value.KeyVault = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamedValueOperatorSpec + err := operatorSpec.AssignProperties_From_NamedValueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamedValueOperatorSpec() to populate field OperatorSpec") + } + value.OperatorSpec = &operatorSpec + } else { + value.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -640,6 +702,18 @@ func (value *NamedValue_Spec) AssignProperties_To_NamedValue_Spec(destination *s destination.KeyVault = nil } + // OperatorSpec + if value.OperatorSpec != nil { + var operatorSpec storage.NamedValueOperatorSpec + err := value.OperatorSpec.AssignProperties_To_NamedValueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamedValueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = value.OriginalVersion() @@ -1282,6 +1356,110 @@ func (properties *KeyVaultContractProperties_STATUS) AssignProperties_To_KeyVaul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamedValueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamedValueOperatorSpec populates our NamedValueOperatorSpec from the provided source NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_From_NamedValueOperatorSpec(source *storage.NamedValueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamedValueOperatorSpec populates the provided destination NamedValueOperatorSpec from our NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_To_NamedValueOperatorSpec(destination *storage.NamedValueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Issue contract Update Properties. type KeyVaultLastAccessStatusContractProperties_STATUS struct { // Code: Last status code for sync and refresh of secret from key vault. diff --git a/v2/api/apimanagement/v1api20220801/named_value_types_gen_test.go b/v2/api/apimanagement/v1api20220801/named_value_types_gen_test.go index fc53c44f24a..bbc0168af0b 100644 --- a/v2/api/apimanagement/v1api20220801/named_value_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/named_value_types_gen_test.go @@ -491,6 +491,103 @@ func AddRelatedPropertyGeneratorsForNamedValue(gens map[string]gopter.Gen) { gens["Status"] = NamedValue_STATUSGenerator() } +func Test_NamedValueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamedValueOperatorSpec to NamedValueOperatorSpec via AssignProperties_To_NamedValueOperatorSpec & AssignProperties_From_NamedValueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamedValueOperatorSpec tests if a specific instance of NamedValueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamedValueOperatorSpec + err := copied.AssignProperties_To_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamedValueOperatorSpec + err = actual.AssignProperties_From_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamedValueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamedValueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamedValueOperatorSpec runs a test to see if a specific instance of NamedValueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamedValueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamedValueOperatorSpec instances for property testing - lazily instantiated by +// NamedValueOperatorSpecGenerator() +var namedValueOperatorSpecGenerator gopter.Gen + +// NamedValueOperatorSpecGenerator returns a generator of NamedValueOperatorSpec instances for property testing. +func NamedValueOperatorSpecGenerator() gopter.Gen { + if namedValueOperatorSpecGenerator != nil { + return namedValueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namedValueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamedValueOperatorSpec{}), generators) + + return namedValueOperatorSpecGenerator +} + func Test_NamedValue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -731,4 +828,5 @@ func AddIndependentPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNamedValue_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.Gen) { gens["KeyVault"] = gen.PtrOf(KeyVaultContractCreatePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamedValueOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen.go b/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen.go index 07450c07dd1..4232c82663e 100644 --- a/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (fragment *PolicyFragment) defaultAzureName() { // defaultImpl applies the code generated defaults to the PolicyFragment resource func (fragment *PolicyFragment) defaultImpl() { fragment.defaultAzureName() } +var _ configmaps.Exporter = &PolicyFragment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fragment *PolicyFragment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PolicyFragment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fragment *PolicyFragment) SecretDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PolicyFragment{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (fragment *PolicyFragment) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (fragment *PolicyFragment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){fragment.validateResourceReferences, fragment.validateOwnerReference} + return []func() (admission.Warnings, error){fragment.validateResourceReferences, fragment.validateOwnerReference, fragment.validateSecretDestinations, fragment.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (fragment *PolicyFragment) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return fragment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return fragment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return fragment.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (fragment *PolicyFragment) validateConfigMapDestinations() (admission.Warnings, error) { + if fragment.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(fragment, nil, fragment.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (fragment *PolicyFragment) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (fragment *PolicyFragment) validateSecretDestinations() (admission.Warnings, error) { + if fragment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(fragment, nil, fragment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (fragment *PolicyFragment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PolicyFragment) @@ -342,6 +387,10 @@ type PolicyFragment_Spec struct { // Format: Format of the policy fragment content. Format *PolicyFragmentContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PolicyFragmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -423,6 +472,8 @@ func (fragment *PolicyFragment_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": fragment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -515,6 +566,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_From_PolicyFragment_Spec(s fragment.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyFragmentOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyFragmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + fragment.OperatorSpec = &operatorSpec + } else { + fragment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -554,6 +617,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_To_PolicyFragment_Spec(des destination.Format = nil } + // OperatorSpec + if fragment.OperatorSpec != nil { + var operatorSpec storage.PolicyFragmentOperatorSpec + err := fragment.OperatorSpec.AssignProperties_To_PolicyFragmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = fragment.OriginalVersion() @@ -857,6 +932,110 @@ var policyFragmentContractProperties_Format_STATUS_Values = map[string]PolicyFra "xml": PolicyFragmentContractProperties_Format_STATUS_Xml, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyFragmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyFragmentOperatorSpec populates our PolicyFragmentOperatorSpec from the provided source PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_From_PolicyFragmentOperatorSpec(source *storage.PolicyFragmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PolicyFragmentOperatorSpec populates the provided destination PolicyFragmentOperatorSpec from our PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_To_PolicyFragmentOperatorSpec(destination *storage.PolicyFragmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PolicyFragment{}, &PolicyFragmentList{}) } diff --git a/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen_test.go b/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen_test.go index ee1918c423f..69db56f42ba 100644 --- a/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/policy_fragment_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForPolicyFragment(gens map[string]gopter.Gen) { gens["Status"] = PolicyFragment_STATUSGenerator() } +func Test_PolicyFragmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyFragmentOperatorSpec to PolicyFragmentOperatorSpec via AssignProperties_To_PolicyFragmentOperatorSpec & AssignProperties_From_PolicyFragmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyFragmentOperatorSpec tests if a specific instance of PolicyFragmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PolicyFragmentOperatorSpec + err := copied.AssignProperties_To_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyFragmentOperatorSpec + err = actual.AssignProperties_From_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyFragmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyFragmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyFragmentOperatorSpec runs a test to see if a specific instance of PolicyFragmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyFragmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyFragmentOperatorSpec instances for property testing - lazily instantiated by +// PolicyFragmentOperatorSpecGenerator() +var policyFragmentOperatorSpecGenerator gopter.Gen + +// PolicyFragmentOperatorSpecGenerator returns a generator of PolicyFragmentOperatorSpec instances for property testing. +func PolicyFragmentOperatorSpecGenerator() gopter.Gen { + if policyFragmentOperatorSpecGenerator != nil { + return policyFragmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyFragmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragmentOperatorSpec{}), generators) + + return policyFragmentOperatorSpecGenerator +} + func Test_PolicyFragment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForPolicyFragment_Spec(subject PolicyFragment_Spec) var policyFragment_SpecGenerator gopter.Gen // PolicyFragment_SpecGenerator returns a generator of PolicyFragment_Spec instances for property testing. +// We first initialize policyFragment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PolicyFragment_SpecGenerator() gopter.Gen { if policyFragment_SpecGenerator != nil { return policyFragment_SpecGenerator @@ -367,6 +467,12 @@ func PolicyFragment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) + AddRelatedPropertyGeneratorsForPolicyFragment_Spec(generators) + policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + return policyFragment_SpecGenerator } @@ -377,3 +483,8 @@ func AddIndependentPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopt gens["Format"] = gen.PtrOf(gen.OneConstOf(PolicyFragmentContractProperties_Format_Rawxml, PolicyFragmentContractProperties_Format_Xml)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicyFragment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyFragmentOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/policy_types_gen.go b/v2/api/apimanagement/v1api20220801/policy_types_gen.go index 411748f24ec..b7bbdd4acc7 100644 --- a/v2/api/apimanagement/v1api20220801/policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *Policy) Default() { // defaultImpl applies the code generated defaults to the Policy resource func (policy *Policy) defaultImpl() {} +var _ configmaps.Exporter = &Policy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *Policy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Policy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *Policy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Policy{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +226,7 @@ func (policy *Policy) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (policy *Policy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -221,9 +244,23 @@ func (policy *Policy) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *Policy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *Policy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -238,6 +275,14 @@ func (policy *Policy) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *Policy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *Policy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Policy) @@ -323,6 +368,10 @@ type Policy_Spec struct { // Format: Format of the policyContent. Format *PolicyContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (policy *Policy_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefere } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -467,6 +518,18 @@ func (policy *Policy_Spec) AssignProperties_From_Policy_Spec(source *storage.Pol policy.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -495,6 +558,18 @@ func (policy *Policy_Spec) AssignProperties_To_Policy_Spec(destination *storage. destination.Format = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.PolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_PolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -777,6 +852,110 @@ var policyContractProperties_Format_STATUS_Values = map[string]PolicyContractPro "xml-link": PolicyContractProperties_Format_STATUS_XmlLink, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyOperatorSpec populates our PolicyOperatorSpec from the provided source PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_From_PolicyOperatorSpec(source *storage.PolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PolicyOperatorSpec populates the provided destination PolicyOperatorSpec from our PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_To_PolicyOperatorSpec(destination *storage.PolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Policy{}, &PolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/policy_types_gen_test.go index f8d4f08ec14..ae3ea2e02ab 100644 --- a/v2/api/apimanagement/v1api20220801/policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/policy_types_gen_test.go @@ -164,6 +164,102 @@ func AddRelatedPropertyGeneratorsForPolicy(gens map[string]gopter.Gen) { gens["Status"] = Policy_STATUSGenerator() } +func Test_PolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyOperatorSpec to PolicyOperatorSpec via AssignProperties_To_PolicyOperatorSpec & AssignProperties_From_PolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyOperatorSpec tests if a specific instance of PolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PolicyOperatorSpec + err := copied.AssignProperties_To_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyOperatorSpec + err = actual.AssignProperties_From_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyOperatorSpec runs a test to see if a specific instance of PolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyOperatorSpec instances for property testing - lazily instantiated by PolicyOperatorSpecGenerator() +var policyOperatorSpecGenerator gopter.Gen + +// PolicyOperatorSpecGenerator returns a generator of PolicyOperatorSpec instances for property testing. +func PolicyOperatorSpecGenerator() gopter.Gen { + if policyOperatorSpecGenerator != nil { + return policyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyOperatorSpec{}), generators) + + return policyOperatorSpecGenerator +} + func Test_Policy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +455,9 @@ func RunJSONSerializationTestForPolicy_Spec(subject Policy_Spec) string { var policy_SpecGenerator gopter.Gen // Policy_SpecGenerator returns a generator of Policy_Spec instances for property testing. +// We first initialize policy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Policy_SpecGenerator() gopter.Gen { if policy_SpecGenerator != nil { return policy_SpecGenerator @@ -368,6 +467,12 @@ func Policy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicy_Spec(generators) policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForPolicy_Spec(generators) + policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + return policy_SpecGenerator } @@ -380,3 +485,8 @@ func AddIndependentPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) PolicyContractProperties_Format_XmlLink)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/product_api_types_gen.go b/v2/api/apimanagement/v1api20220801/product_api_types_gen.go index 4ced6eb22e7..7f2a646a304 100644 --- a/v2/api/apimanagement/v1api20220801/product_api_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/product_api_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (productApi *ProductApi) defaultAzureName() { // defaultImpl applies the code generated defaults to the ProductApi resource func (productApi *ProductApi) defaultImpl() { productApi.defaultAzureName() } +var _ configmaps.Exporter = &ProductApi{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (productApi *ProductApi) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductApi{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (productApi *ProductApi) SecretDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ProductApi{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (productApi *ProductApi) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (productApi *ProductApi) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){productApi.validateResourceReferences, productApi.validateOwnerReference} + return []func() (admission.Warnings, error){productApi.validateResourceReferences, productApi.validateOwnerReference, productApi.validateSecretDestinations, productApi.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (productApi *ProductApi) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return productApi.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return productApi.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return productApi.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (productApi *ProductApi) validateConfigMapDestinations() (admission.Warnings, error) { + if productApi.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(productApi, nil, productApi.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (productApi *ProductApi) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(productApi) @@ -244,6 +281,14 @@ func (productApi *ProductApi) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (productApi *ProductApi) validateSecretDestinations() (admission.Warnings, error) { + if productApi.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(productApi, nil, productApi.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (productApi *ProductApi) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ProductApi) @@ -333,6 +378,10 @@ type ProductApi_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductApiOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -369,6 +418,8 @@ func (productApi *ProductApi_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": productApi.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": productApi.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -435,6 +486,18 @@ func (productApi *ProductApi_Spec) AssignProperties_From_ProductApi_Spec(source // AzureName productApi.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductApiOperatorSpec + err := operatorSpec.AssignProperties_From_ProductApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductApiOperatorSpec() to populate field OperatorSpec") + } + productApi.OperatorSpec = &operatorSpec + } else { + productApi.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -455,6 +518,18 @@ func (productApi *ProductApi_Spec) AssignProperties_To_ProductApi_Spec(destinati // AzureName destination.AzureName = productApi.AzureName + // OperatorSpec + if productApi.OperatorSpec != nil { + var operatorSpec storage.ProductApiOperatorSpec + err := productApi.OperatorSpec.AssignProperties_To_ProductApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = productApi.OriginalVersion() @@ -596,6 +671,110 @@ func (productApi *ProductApi_STATUS) AssignProperties_To_ProductApi_STATUS(desti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductApiOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductApiOperatorSpec populates our ProductApiOperatorSpec from the provided source ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_From_ProductApiOperatorSpec(source *storage.ProductApiOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductApiOperatorSpec populates the provided destination ProductApiOperatorSpec from our ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_To_ProductApiOperatorSpec(destination *storage.ProductApiOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ProductApi{}, &ProductApiList{}) } diff --git a/v2/api/apimanagement/v1api20220801/product_api_types_gen_test.go b/v2/api/apimanagement/v1api20220801/product_api_types_gen_test.go index 92d0a9599ee..45ac87b69c8 100644 --- a/v2/api/apimanagement/v1api20220801/product_api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/product_api_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProductApi(gens map[string]gopter.Gen) { gens["Status"] = ProductApi_STATUSGenerator() } +func Test_ProductApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductApiOperatorSpec to ProductApiOperatorSpec via AssignProperties_To_ProductApiOperatorSpec & AssignProperties_From_ProductApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductApiOperatorSpec tests if a specific instance of ProductApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductApiOperatorSpec + err := copied.AssignProperties_To_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductApiOperatorSpec + err = actual.AssignProperties_From_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductApiOperatorSpec runs a test to see if a specific instance of ProductApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductApiOperatorSpec instances for property testing - lazily instantiated by +// ProductApiOperatorSpecGenerator() +var productApiOperatorSpecGenerator gopter.Gen + +// ProductApiOperatorSpecGenerator returns a generator of ProductApiOperatorSpec instances for property testing. +func ProductApiOperatorSpecGenerator() gopter.Gen { + if productApiOperatorSpecGenerator != nil { + return productApiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productApiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductApiOperatorSpec{}), generators) + + return productApiOperatorSpecGenerator +} + func Test_ProductApi_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -345,6 +442,9 @@ func RunJSONSerializationTestForProductApi_Spec(subject ProductApi_Spec) string var productApi_SpecGenerator gopter.Gen // ProductApi_SpecGenerator returns a generator of ProductApi_Spec instances for property testing. +// We first initialize productApi_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductApi_SpecGenerator() gopter.Gen { if productApi_SpecGenerator != nil { return productApi_SpecGenerator @@ -354,6 +454,12 @@ func ProductApi_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductApi_Spec(generators) productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductApi_Spec(generators) + AddRelatedPropertyGeneratorsForProductApi_Spec(generators) + productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + return productApi_SpecGenerator } @@ -361,3 +467,8 @@ func ProductApi_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { gens["AzureName"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForProductApi_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductApiOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/product_policy_types_gen.go b/v2/api/apimanagement/v1api20220801/product_policy_types_gen.go index 79321934197..5bcc4f963c6 100644 --- a/v2/api/apimanagement/v1api20220801/product_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/product_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ProductPolicy) Default() { // defaultImpl applies the code generated defaults to the ProductPolicy resource func (policy *ProductPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ProductPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ProductPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ProductPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ProductPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +226,7 @@ func (policy *ProductPolicy) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (policy *ProductPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -221,9 +244,23 @@ func (policy *ProductPolicy) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ProductPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *ProductPolicy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -238,6 +275,14 @@ func (policy *ProductPolicy) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ProductPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ProductPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ProductPolicy) @@ -323,6 +368,10 @@ type ProductPolicy_Spec struct { // Format: Format of the policyContent. Format *PolicyContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (policy *ProductPolicy_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -467,6 +518,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_From_ProductPolicy_Spec(sourc policy.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ProductPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -495,6 +558,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_To_ProductPolicy_Spec(destina destination.Format = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ProductPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ProductPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -742,6 +817,110 @@ func (policy *ProductPolicy_STATUS) AssignProperties_To_ProductPolicy_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductPolicyOperatorSpec populates our ProductPolicyOperatorSpec from the provided source ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_From_ProductPolicyOperatorSpec(source *storage.ProductPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductPolicyOperatorSpec populates the provided destination ProductPolicyOperatorSpec from our ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_To_ProductPolicyOperatorSpec(destination *storage.ProductPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ProductPolicy{}, &ProductPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/product_policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/product_policy_types_gen_test.go index bf7da9d0742..561228db991 100644 --- a/v2/api/apimanagement/v1api20220801/product_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/product_policy_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProductPolicy(gens map[string]gopter.Gen) { gens["Status"] = ProductPolicy_STATUSGenerator() } +func Test_ProductPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductPolicyOperatorSpec to ProductPolicyOperatorSpec via AssignProperties_To_ProductPolicyOperatorSpec & AssignProperties_From_ProductPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductPolicyOperatorSpec tests if a specific instance of ProductPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductPolicyOperatorSpec + err := copied.AssignProperties_To_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductPolicyOperatorSpec + err = actual.AssignProperties_From_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductPolicyOperatorSpec runs a test to see if a specific instance of ProductPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductPolicyOperatorSpec instances for property testing - lazily instantiated by +// ProductPolicyOperatorSpecGenerator() +var productPolicyOperatorSpecGenerator gopter.Gen + +// ProductPolicyOperatorSpecGenerator returns a generator of ProductPolicyOperatorSpec instances for property testing. +func ProductPolicyOperatorSpecGenerator() gopter.Gen { + if productPolicyOperatorSpecGenerator != nil { + return productPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicyOperatorSpec{}), generators) + + return productPolicyOperatorSpecGenerator +} + func Test_ProductPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForProductPolicy_Spec(subject ProductPolicy_Spec) s var productPolicy_SpecGenerator gopter.Gen // ProductPolicy_SpecGenerator returns a generator of ProductPolicy_Spec instances for property testing. +// We first initialize productPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductPolicy_SpecGenerator() gopter.Gen { if productPolicy_SpecGenerator != nil { return productPolicy_SpecGenerator @@ -369,6 +469,12 @@ func ProductPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForProductPolicy_Spec(generators) + productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + return productPolicy_SpecGenerator } @@ -381,3 +487,8 @@ func AddIndependentPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopte PolicyContractProperties_Format_XmlLink)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProductPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/product_types_gen.go b/v2/api/apimanagement/v1api20220801/product_types_gen.go index f8bec52f7db..ed190682a44 100644 --- a/v2/api/apimanagement/v1api20220801/product_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/product_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (product *Product) defaultAzureName() { // defaultImpl applies the code generated defaults to the Product resource func (product *Product) defaultImpl() { product.defaultAzureName() } +var _ configmaps.Exporter = &Product{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (product *Product) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Product{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (product *Product) SecretDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Product{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (product *Product) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (product *Product) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){product.validateResourceReferences, product.validateOwnerReference} + return []func() (admission.Warnings, error){product.validateResourceReferences, product.validateOwnerReference, product.validateSecretDestinations, product.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,9 +251,23 @@ func (product *Product) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return product.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return product.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return product.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (product *Product) validateConfigMapDestinations() (admission.Warnings, error) { + if product.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(product, nil, product.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (product *Product) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(product) @@ -245,6 +282,14 @@ func (product *Product) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (product *Product) validateSecretDestinations() (admission.Warnings, error) { + if product.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(product, nil, product.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (product *Product) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Product) @@ -350,6 +395,10 @@ type Product_Spec struct { // DisplayName: Product name. DisplayName *string `json:"displayName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -474,6 +523,8 @@ func (product *Product_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": product.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -602,6 +653,18 @@ func (product *Product_Spec) AssignProperties_From_Product_Spec(source *storage. product.DisplayName = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductOperatorSpec + err := operatorSpec.AssignProperties_From_ProductOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductOperatorSpec() to populate field OperatorSpec") + } + product.OperatorSpec = &operatorSpec + } else { + product.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -669,6 +732,18 @@ func (product *Product_Spec) AssignProperties_To_Product_Spec(destination *stora destination.DisplayName = nil } + // OperatorSpec + if product.OperatorSpec != nil { + var operatorSpec storage.ProductOperatorSpec + err := product.OperatorSpec.AssignProperties_To_ProductOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = product.OriginalVersion() @@ -1121,6 +1196,110 @@ var productContractProperties_State_STATUS_Values = map[string]ProductContractPr "published": ProductContractProperties_State_STATUS_Published, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductOperatorSpec populates our ProductOperatorSpec from the provided source ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_From_ProductOperatorSpec(source *storage.ProductOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductOperatorSpec populates the provided destination ProductOperatorSpec from our ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_To_ProductOperatorSpec(destination *storage.ProductOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Product{}, &ProductList{}) } diff --git a/v2/api/apimanagement/v1api20220801/product_types_gen_test.go b/v2/api/apimanagement/v1api20220801/product_types_gen_test.go index f4fa97e4911..84f757003c7 100644 --- a/v2/api/apimanagement/v1api20220801/product_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/product_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProduct(gens map[string]gopter.Gen) { gens["Status"] = Product_STATUSGenerator() } +func Test_ProductOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductOperatorSpec to ProductOperatorSpec via AssignProperties_To_ProductOperatorSpec & AssignProperties_From_ProductOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductOperatorSpec tests if a specific instance of ProductOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductOperatorSpec + err := copied.AssignProperties_To_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductOperatorSpec + err = actual.AssignProperties_From_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductOperatorSpec runs a test to see if a specific instance of ProductOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductOperatorSpec instances for property testing - lazily instantiated by +// ProductOperatorSpecGenerator() +var productOperatorSpecGenerator gopter.Gen + +// ProductOperatorSpecGenerator returns a generator of ProductOperatorSpec instances for property testing. +func ProductOperatorSpecGenerator() gopter.Gen { + if productOperatorSpecGenerator != nil { + return productOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductOperatorSpec{}), generators) + + return productOperatorSpecGenerator +} + func Test_Product_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForProduct_Spec(subject Product_Spec) string { var product_SpecGenerator gopter.Gen // Product_SpecGenerator returns a generator of Product_Spec instances for property testing. +// We first initialize product_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Product_SpecGenerator() gopter.Gen { if product_SpecGenerator != nil { return product_SpecGenerator @@ -369,6 +469,12 @@ func Product_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProduct_Spec(generators) product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProduct_Spec(generators) + AddRelatedPropertyGeneratorsForProduct_Spec(generators) + product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + return product_SpecGenerator } @@ -383,3 +489,8 @@ func AddIndependentPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) gens["SubscriptionsLimit"] = gen.PtrOf(gen.Int()) gens["Terms"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProduct_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/service_types_gen.go b/v2/api/apimanagement/v1api20220801/service_types_gen.go index ec3c8217a4a..ad03c37aa77 100644 --- a/v2/api/apimanagement/v1api20220801/service_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/service_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (service *Service) defaultAzureName() { // defaultImpl applies the code generated defaults to the Service resource func (service *Service) defaultImpl() { service.defaultAzureName() } +var _ configmaps.Exporter = &Service{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *Service) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Service{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *Service) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Service{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (service *Service) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (service *Service) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations, service.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (service *Service) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return service.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *Service) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (service *Service) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&service.Spec) @@ -257,6 +293,14 @@ func (service *Service) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *Service) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *Service) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Service) @@ -405,6 +449,10 @@ type Service_Spec struct { // NotificationSenderEmail: Email address from which the notification will be sent. NotificationSenderEmail *string `json:"notificationSenderEmail,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -754,6 +802,8 @@ func (service *Service_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1026,6 +1076,18 @@ func (service *Service_Spec) AssignProperties_From_Service_Spec(source *storage. service.NotificationSenderEmail = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServiceOperatorSpec + err := operatorSpec.AssignProperties_From_ServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1242,6 +1304,18 @@ func (service *Service_Spec) AssignProperties_To_Service_Spec(destination *stora destination.NotificationSenderEmail = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.ServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_ServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -5499,6 +5573,110 @@ func (wrapper *RemotePrivateEndpointConnectionWrapper_STATUS) AssignProperties_T return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServiceOperatorSpec populates our ServiceOperatorSpec from the provided source ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_From_ServiceOperatorSpec(source *storage.ServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServiceOperatorSpec populates the provided destination ServiceOperatorSpec from our ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_To_ServiceOperatorSpec(destination *storage.ServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/apimanagement/v1api20220801/service_types_gen_test.go b/v2/api/apimanagement/v1api20220801/service_types_gen_test.go index b761fd89fbd..d136d12f60a 100644 --- a/v2/api/apimanagement/v1api20220801/service_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/service_types_gen_test.go @@ -2131,6 +2131,103 @@ func AddRelatedPropertyGeneratorsForService(gens map[string]gopter.Gen) { gens["Status"] = Service_STATUSGenerator() } +func Test_ServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServiceOperatorSpec to ServiceOperatorSpec via AssignProperties_To_ServiceOperatorSpec & AssignProperties_From_ServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServiceOperatorSpec tests if a specific instance of ServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServiceOperatorSpec + err := copied.AssignProperties_To_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServiceOperatorSpec + err = actual.AssignProperties_From_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServiceOperatorSpec runs a test to see if a specific instance of ServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServiceOperatorSpec instances for property testing - lazily instantiated by +// ServiceOperatorSpecGenerator() +var serviceOperatorSpecGenerator gopter.Gen + +// ServiceOperatorSpecGenerator returns a generator of ServiceOperatorSpec instances for property testing. +func ServiceOperatorSpecGenerator() gopter.Gen { + if serviceOperatorSpecGenerator != nil { + return serviceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serviceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServiceOperatorSpec{}), generators) + + return serviceOperatorSpecGenerator +} + func Test_Service_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2428,6 +2525,7 @@ func AddRelatedPropertyGeneratorsForService_Spec(gens map[string]gopter.Gen) { gens["Certificates"] = gen.SliceOf(CertificateConfigurationGenerator()) gens["HostnameConfigurations"] = gen.SliceOf(HostnameConfigurationGenerator()) gens["Identity"] = gen.PtrOf(ApiManagementServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServiceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(ApiManagementServiceSkuPropertiesGenerator()) gens["VirtualNetworkConfiguration"] = gen.PtrOf(VirtualNetworkConfigurationGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/storage/api_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/api_types_gen.go index 8107b6d0345..1df8beb031e 100644 --- a/v2/api/apimanagement/v1api20220801/storage/api_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/api_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -42,6 +45,26 @@ func (api *Api) GetConditions() conditions.Conditions { // SetConditions sets the conditions on the resource status func (api *Api) SetConditions(conditions conditions.Conditions) { api.Status.Conditions = conditions } +var _ configmaps.Exporter = &Api{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (api *Api) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Api{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (api *Api) SecretDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Api{} // AzureName returns the Azure name of the resource @@ -159,6 +182,7 @@ type Api_Spec struct { Format *string `json:"format,omitempty"` IsCurrent *bool `json:"isCurrent,omitempty"` License *ApiLicenseInformation `json:"license,omitempty"` + OperatorSpec *ApiOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -299,6 +323,14 @@ type ApiLicenseInformation_STATUS struct { Url *string `json:"url,omitempty"` } +// Storage version of v1api20220801.ApiOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220801.ApiVersionSetContractDetails // An API Version Set contains the common configuration for a set of API Versions relating type ApiVersionSetContractDetails struct { diff --git a/v2/api/apimanagement/v1api20220801/storage/api_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/api_types_gen_test.go index fe4ccaa19bd..a7fc98d4024 100644 --- a/v2/api/apimanagement/v1api20220801/storage/api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/api_types_gen_test.go @@ -390,6 +390,60 @@ func AddIndependentPropertyGeneratorsForApiLicenseInformation_STATUS(gens map[st gens["Url"] = gen.PtrOf(gen.AlphaString()) } +func Test_ApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiOperatorSpec runs a test to see if a specific instance of ApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiOperatorSpec instances for property testing - lazily instantiated by ApiOperatorSpecGenerator() +var apiOperatorSpecGenerator gopter.Gen + +// ApiOperatorSpecGenerator returns a generator of ApiOperatorSpec instances for property testing. +func ApiOperatorSpecGenerator() gopter.Gen { + if apiOperatorSpecGenerator != nil { + return apiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiOperatorSpec{}), generators) + + return apiOperatorSpecGenerator +} + func Test_ApiVersionSetContractDetails_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -710,6 +764,7 @@ func AddRelatedPropertyGeneratorsForApi_Spec(gens map[string]gopter.Gen) { gens["AuthenticationSettings"] = gen.PtrOf(AuthenticationSettingsContractGenerator()) gens["Contact"] = gen.PtrOf(ApiContactInformationGenerator()) gens["License"] = gen.PtrOf(ApiLicenseInformationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApiOperatorSpecGenerator()) gens["SubscriptionKeyParameterNames"] = gen.PtrOf(SubscriptionKeyParameterNamesContractGenerator()) gens["WsdlSelector"] = gen.PtrOf(ApiCreateOrUpdateProperties_WsdlSelectorGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen.go index 740ad105a5e..5faa130b8e7 100644 --- a/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (versionSet *ApiVersionSet) SetConditions(conditions conditions.Conditions) versionSet.Status.Conditions = conditions } +var _ configmaps.Exporter = &ApiVersionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (versionSet *ApiVersionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApiVersionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (versionSet *ApiVersionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ApiVersionSet{} // AzureName returns the Azure name of the resource @@ -143,10 +166,11 @@ type ApiVersionSetList struct { type ApiVersionSet_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + OperatorSpec *ApiVersionSetOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -213,6 +237,14 @@ func (versionSet *ApiVersionSet_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(versionSet) } +// Storage version of v1api20220801.ApiVersionSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiVersionSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ApiVersionSet{}, &ApiVersionSetList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen_test.go index 3f2be2c7086..dc266281b84 100644 --- a/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/api_version_set_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForApiVersionSet(gens map[string]gopter.Gen) { gens["Status"] = ApiVersionSet_STATUSGenerator() } +func Test_ApiVersionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiVersionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiVersionSetOperatorSpec runs a test to see if a specific instance of ApiVersionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiVersionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiVersionSetOperatorSpec instances for property testing - lazily instantiated by +// ApiVersionSetOperatorSpecGenerator() +var apiVersionSetOperatorSpecGenerator gopter.Gen + +// ApiVersionSetOperatorSpecGenerator returns a generator of ApiVersionSetOperatorSpec instances for property testing. +func ApiVersionSetOperatorSpecGenerator() gopter.Gen { + if apiVersionSetOperatorSpecGenerator != nil { + return apiVersionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiVersionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSetOperatorSpec{}), generators) + + return apiVersionSetOperatorSpecGenerator +} + func Test_ApiVersionSet_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -189,6 +244,9 @@ func RunJSONSerializationTestForApiVersionSet_Spec(subject ApiVersionSet_Spec) s var apiVersionSet_SpecGenerator gopter.Gen // ApiVersionSet_SpecGenerator returns a generator of ApiVersionSet_Spec instances for property testing. +// We first initialize apiVersionSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApiVersionSet_SpecGenerator() gopter.Gen { if apiVersionSet_SpecGenerator != nil { return apiVersionSet_SpecGenerator @@ -198,6 +256,12 @@ func ApiVersionSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) + AddRelatedPropertyGeneratorsForApiVersionSet_Spec(generators) + apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + return apiVersionSet_SpecGenerator } @@ -211,3 +275,8 @@ func AddIndependentPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopte gens["VersionQueryName"] = gen.PtrOf(gen.AlphaString()) gens["VersioningScheme"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForApiVersionSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApiVersionSetOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen.go index 18aa3f96e51..18b3808512d 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (provider *AuthorizationProvider) SetConditions(conditions conditions.Condi provider.Status.Conditions = conditions } +var _ configmaps.Exporter = &AuthorizationProvider{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (provider *AuthorizationProvider) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvider{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (provider *AuthorizationProvider) SecretDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvider{} // AzureName returns the Azure name of the resource @@ -146,6 +169,7 @@ type AuthorizationProvider_Spec struct { DisplayName *string `json:"displayName,omitempty"` IdentityProvider *string `json:"identityProvider,omitempty"` Oauth2 *AuthorizationProviderOAuth2Settings `json:"oauth2,omitempty"` + OperatorSpec *AuthorizationProviderOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -224,6 +248,14 @@ type AuthorizationProviderOAuth2Settings_STATUS struct { RedirectUrl *string `json:"redirectUrl,omitempty"` } +// Storage version of v1api20220801.AuthorizationProviderOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProviderOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220801.AuthorizationProviderOAuth2GrantTypes // Authorization Provider oauth2 grant types settings type AuthorizationProviderOAuth2GrantTypes struct { diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen_test.go index bfb23313c81..a43325ea5d4 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_provider_types_gen_test.go @@ -350,6 +350,61 @@ func AddRelatedPropertyGeneratorsForAuthorizationProviderOAuth2Settings_STATUS(g gens["GrantTypes"] = gen.PtrOf(AuthorizationProviderOAuth2GrantTypes_STATUSGenerator()) } +func Test_AuthorizationProviderOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProviderOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProviderOperatorSpec runs a test to see if a specific instance of AuthorizationProviderOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProviderOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProviderOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProviderOperatorSpecGenerator() +var authorizationProviderOperatorSpecGenerator gopter.Gen + +// AuthorizationProviderOperatorSpecGenerator returns a generator of AuthorizationProviderOperatorSpec instances for property testing. +func AuthorizationProviderOperatorSpecGenerator() gopter.Gen { + if authorizationProviderOperatorSpecGenerator != nil { + return authorizationProviderOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProviderOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProviderOperatorSpec{}), generators) + + return authorizationProviderOperatorSpecGenerator +} + func Test_AuthorizationProvider_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -505,4 +560,5 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvider_Spec(gens map[stri // AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec(gens map[string]gopter.Gen) { gens["Oauth2"] = gen.PtrOf(AuthorizationProviderOAuth2SettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProviderOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen.go index 202a9b2ea4b..537adce090f 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (authorization *AuthorizationProvidersAuthorization) SetConditions(conditio authorization.Status.Conditions = conditions } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorization{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authorization *AuthorizationProvidersAuthorization) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorization{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authorization *AuthorizationProvidersAuthorization) SecretDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorization{} // AzureName returns the Azure name of the resource @@ -144,9 +167,10 @@ type AuthorizationProvidersAuthorization_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Oauth2GrantType *string `json:"oauth2grantType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Oauth2GrantType *string `json:"oauth2grantType,omitempty"` + OperatorSpec *AuthorizationProvidersAuthorizationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -219,6 +243,14 @@ type AuthorizationError_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220801.AuthorizationProvidersAuthorizationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorization{}, &AuthorizationProvidersAuthorizationList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen_test.go index ff84234d660..8e08dd1f480 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorization_types_gen_test.go @@ -141,6 +141,61 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization(gens map gens["Status"] = AuthorizationProvidersAuthorization_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProvidersAuthorizationOperatorSpecGenerator() +var authorizationProvidersAuthorizationOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorization_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -268,6 +323,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorization_Spec(subject var authorizationProvidersAuthorization_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorization_SpecGenerator returns a generator of AuthorizationProvidersAuthorization_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorization_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorization_SpecGenerator != nil { return authorizationProvidersAuthorization_SpecGenerator @@ -277,6 +335,12 @@ func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + return authorizationProvidersAuthorization_SpecGenerator } @@ -287,3 +351,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec gens["Oauth2GrantType"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen.go index dd8716dea34..ba903e96d4d 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) SetConditions(co policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorizationsAccessPolicy{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type AuthorizationProvidersAuthorizationsAccessPolicyList struct { type AuthorizationProvidersAuthorizationsAccessPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ObjectId *string `json:"objectId,omitempty" optionalConfigMapPair:"ObjectId"` - ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ObjectId *string `json:"objectId,omitempty" optionalConfigMapPair:"ObjectId"` + ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` + OperatorSpec *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -208,6 +232,14 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) ConvertSt return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20220801.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorizationsAccessPolicy{}, &AuthorizationProvidersAuthorizationsAccessPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen_test.go index 02878bf2c59..1581dd1d990 100644 --- a/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/authorization_providers_authorizations_access_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPo gens["Status"] = AuthorizationProvidersAuthorizationsAccessPolicy_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing - lazily +// instantiated by AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() +var authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorizationsAccessPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicy var authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicy_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator != nil { return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator @@ -197,6 +255,12 @@ func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator } @@ -207,3 +271,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAcce gens["OriginalVersion"] = gen.AlphaString() gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/backend_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/backend_types_gen.go index 3c48efc9e4a..7ac29a7affb 100644 --- a/v2/api/apimanagement/v1api20220801/storage/backend_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/backend_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (backend *Backend) SetConditions(conditions conditions.Conditions) { backend.Status.Conditions = conditions } +var _ configmaps.Exporter = &Backend{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (backend *Backend) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Backend{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (backend *Backend) SecretDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Backend{} // AzureName returns the Azure name of the resource @@ -146,6 +169,7 @@ type Backend_Spec struct { AzureName string `json:"azureName,omitempty"` Credentials *BackendCredentialsContract `json:"credentials,omitempty"` Description *string `json:"description,omitempty"` + OperatorSpec *BackendOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -246,6 +270,14 @@ type BackendCredentialsContract_STATUS struct { Query map[string][]string `json:"query,omitempty"` } +// Storage version of v1api20220801.BackendOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackendOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220801.BackendProperties // Properties specific to the Backend Type. type BackendProperties struct { diff --git a/v2/api/apimanagement/v1api20220801/storage/backend_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/backend_types_gen_test.go index 107b49990ad..858bbff9a9a 100644 --- a/v2/api/apimanagement/v1api20220801/storage/backend_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/backend_types_gen_test.go @@ -366,6 +366,61 @@ func AddRelatedPropertyGeneratorsForBackendCredentialsContract_STATUS(gens map[s gens["Authorization"] = gen.PtrOf(BackendAuthorizationHeaderCredentials_STATUSGenerator()) } +func Test_BackendOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackendOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackendOperatorSpec runs a test to see if a specific instance of BackendOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackendOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackendOperatorSpec instances for property testing - lazily instantiated by +// BackendOperatorSpecGenerator() +var backendOperatorSpecGenerator gopter.Gen + +// BackendOperatorSpecGenerator returns a generator of BackendOperatorSpec instances for property testing. +func BackendOperatorSpecGenerator() gopter.Gen { + if backendOperatorSpecGenerator != nil { + return backendOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backendOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackendOperatorSpec{}), generators) + + return backendOperatorSpecGenerator +} + func Test_BackendProperties_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1054,6 +1109,7 @@ func AddIndependentPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForBackend_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) { gens["Credentials"] = gen.PtrOf(BackendCredentialsContractGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BackendOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BackendPropertiesGenerator()) gens["Proxy"] = gen.PtrOf(BackendProxyContractGenerator()) gens["Tls"] = gen.PtrOf(BackendTlsPropertiesGenerator()) diff --git a/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen.go index c8aa0c1d431..aff40e8a7ec 100644 --- a/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (value *NamedValue) SetConditions(conditions conditions.Conditions) { value.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamedValue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (value *NamedValue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamedValue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (value *NamedValue) SecretDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamedValue{} // AzureName returns the Azure name of the resource @@ -146,6 +169,7 @@ type NamedValue_Spec struct { AzureName string `json:"azureName,omitempty"` DisplayName *string `json:"displayName,omitempty"` KeyVault *KeyVaultContractCreateProperties `json:"keyVault,omitempty"` + OperatorSpec *NamedValueOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -231,6 +255,14 @@ type KeyVaultContractProperties_STATUS struct { SecretIdentifier *string `json:"secretIdentifier,omitempty"` } +// Storage version of v1api20220801.NamedValueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamedValueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220801.KeyVaultLastAccessStatusContractProperties_STATUS // Issue contract Update Properties. type KeyVaultLastAccessStatusContractProperties_STATUS struct { diff --git a/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen_test.go index 2567f76118d..679b691cb22 100644 --- a/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/named_value_types_gen_test.go @@ -279,6 +279,61 @@ func AddRelatedPropertyGeneratorsForNamedValue(gens map[string]gopter.Gen) { gens["Status"] = NamedValue_STATUSGenerator() } +func Test_NamedValueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamedValueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamedValueOperatorSpec runs a test to see if a specific instance of NamedValueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamedValueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamedValueOperatorSpec instances for property testing - lazily instantiated by +// NamedValueOperatorSpecGenerator() +var namedValueOperatorSpecGenerator gopter.Gen + +// NamedValueOperatorSpecGenerator returns a generator of NamedValueOperatorSpec instances for property testing. +func NamedValueOperatorSpecGenerator() gopter.Gen { + if namedValueOperatorSpecGenerator != nil { + return namedValueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namedValueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamedValueOperatorSpec{}), generators) + + return namedValueOperatorSpecGenerator +} + func Test_NamedValue_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -436,4 +491,5 @@ func AddIndependentPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNamedValue_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.Gen) { gens["KeyVault"] = gen.PtrOf(KeyVaultContractCreatePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamedValueOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen.go index f69d9520767..fe3dfb22298 100644 --- a/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (fragment *PolicyFragment) SetConditions(conditions conditions.Conditions) fragment.Status.Conditions = conditions } +var _ configmaps.Exporter = &PolicyFragment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fragment *PolicyFragment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PolicyFragment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fragment *PolicyFragment) SecretDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PolicyFragment{} // AzureName returns the Azure name of the resource @@ -143,10 +166,11 @@ type PolicyFragmentList struct { type PolicyFragment_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *PolicyFragmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (fragment *PolicyFragment_STATUS) ConvertStatusTo(destination genruntime.Co return destination.ConvertStatusFrom(fragment) } +// Storage version of v1api20220801.PolicyFragmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyFragmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PolicyFragment{}, &PolicyFragmentList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen_test.go index bdd8487dad9..93187974e71 100644 --- a/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/policy_fragment_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForPolicyFragment(gens map[string]gopter.Gen) { gens["Status"] = PolicyFragment_STATUSGenerator() } +func Test_PolicyFragmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyFragmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyFragmentOperatorSpec runs a test to see if a specific instance of PolicyFragmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyFragmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyFragmentOperatorSpec instances for property testing - lazily instantiated by +// PolicyFragmentOperatorSpecGenerator() +var policyFragmentOperatorSpecGenerator gopter.Gen + +// PolicyFragmentOperatorSpecGenerator returns a generator of PolicyFragmentOperatorSpec instances for property testing. +func PolicyFragmentOperatorSpecGenerator() gopter.Gen { + if policyFragmentOperatorSpecGenerator != nil { + return policyFragmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyFragmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragmentOperatorSpec{}), generators) + + return policyFragmentOperatorSpecGenerator +} + func Test_PolicyFragment_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForPolicyFragment_Spec(subject PolicyFragment_Spec) var policyFragment_SpecGenerator gopter.Gen // PolicyFragment_SpecGenerator returns a generator of PolicyFragment_Spec instances for property testing. +// We first initialize policyFragment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PolicyFragment_SpecGenerator() gopter.Gen { if policyFragment_SpecGenerator != nil { return policyFragment_SpecGenerator @@ -197,6 +255,12 @@ func PolicyFragment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) + AddRelatedPropertyGeneratorsForPolicyFragment_Spec(generators) + policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + return policyFragment_SpecGenerator } @@ -208,3 +272,8 @@ func AddIndependentPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopt gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicyFragment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyFragmentOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/policy_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/policy_types_gen.go index 1a0eb9cc7af..37d39c6e4ce 100644 --- a/v2/api/apimanagement/v1api20220801/storage/policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *Policy) SetConditions(conditions conditions.Conditions) { policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &Policy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *Policy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Policy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *Policy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Policy{} // AzureName returns the Azure name of the resource (always "policy") @@ -141,8 +164,9 @@ type PolicyList struct { // Storage version of v1api20220801.Policy_Spec type Policy_Spec struct { - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *PolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (policy *Policy_STATUS) ConvertStatusTo(destination genruntime.ConvertibleS return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20220801.PolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&Policy{}, &PolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/policy_types_gen_test.go index 35731c79800..b4cdcf3e655 100644 --- a/v2/api/apimanagement/v1api20220801/storage/policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/policy_types_gen_test.go @@ -78,6 +78,60 @@ func AddRelatedPropertyGeneratorsForPolicy(gens map[string]gopter.Gen) { gens["Status"] = Policy_STATUSGenerator() } +func Test_PolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyOperatorSpec runs a test to see if a specific instance of PolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyOperatorSpec instances for property testing - lazily instantiated by PolicyOperatorSpecGenerator() +var policyOperatorSpecGenerator gopter.Gen + +// PolicyOperatorSpecGenerator returns a generator of PolicyOperatorSpec instances for property testing. +func PolicyOperatorSpecGenerator() gopter.Gen { + if policyOperatorSpecGenerator != nil { + return policyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyOperatorSpec{}), generators) + + return policyOperatorSpecGenerator +} + func Test_Policy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -185,6 +239,9 @@ func RunJSONSerializationTestForPolicy_Spec(subject Policy_Spec) string { var policy_SpecGenerator gopter.Gen // Policy_SpecGenerator returns a generator of Policy_Spec instances for property testing. +// We first initialize policy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Policy_SpecGenerator() gopter.Gen { if policy_SpecGenerator != nil { return policy_SpecGenerator @@ -194,6 +251,12 @@ func Policy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicy_Spec(generators) policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForPolicy_Spec(generators) + policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + return policy_SpecGenerator } @@ -203,3 +266,8 @@ func AddIndependentPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen.go index b59cf1d6835..d222fe7fc91 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (productApi *ProductApi) SetConditions(conditions conditions.Conditions) { productApi.Status.Conditions = conditions } +var _ configmaps.Exporter = &ProductApi{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (productApi *ProductApi) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductApi{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (productApi *ProductApi) SecretDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductApi{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type ProductApiList struct { type ProductApi_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *ProductApiOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -199,6 +223,14 @@ func (productApi *ProductApi_STATUS) ConvertStatusTo(destination genruntime.Conv return destination.ConvertStatusFrom(productApi) } +// Storage version of v1api20220801.ProductApiOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductApiOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ProductApi{}, &ProductApiList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen_test.go index 6c586b57c9d..0d94a4d64d4 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_api_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForProductApi(gens map[string]gopter.Gen) { gens["Status"] = ProductApi_STATUSGenerator() } +func Test_ProductApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductApiOperatorSpec runs a test to see if a specific instance of ProductApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductApiOperatorSpec instances for property testing - lazily instantiated by +// ProductApiOperatorSpecGenerator() +var productApiOperatorSpecGenerator gopter.Gen + +// ProductApiOperatorSpecGenerator returns a generator of ProductApiOperatorSpec instances for property testing. +func ProductApiOperatorSpecGenerator() gopter.Gen { + if productApiOperatorSpecGenerator != nil { + return productApiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productApiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductApiOperatorSpec{}), generators) + + return productApiOperatorSpecGenerator +} + func Test_ProductApi_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -175,6 +230,9 @@ func RunJSONSerializationTestForProductApi_Spec(subject ProductApi_Spec) string var productApi_SpecGenerator gopter.Gen // ProductApi_SpecGenerator returns a generator of ProductApi_Spec instances for property testing. +// We first initialize productApi_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductApi_SpecGenerator() gopter.Gen { if productApi_SpecGenerator != nil { return productApi_SpecGenerator @@ -184,6 +242,12 @@ func ProductApi_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductApi_Spec(generators) productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductApi_Spec(generators) + AddRelatedPropertyGeneratorsForProductApi_Spec(generators) + productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + return productApi_SpecGenerator } @@ -192,3 +256,8 @@ func AddIndependentPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.G gens["AzureName"] = gen.AlphaString() gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForProductApi_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductApiOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen.go index 192d7496a73..1f24c086de0 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ProductPolicy) SetConditions(conditions conditions.Conditions) { policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ProductPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ProductPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ProductPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductPolicy{} // AzureName returns the Azure name of the resource (always "policy") @@ -141,8 +164,9 @@ type ProductPolicyList struct { // Storage version of v1api20220801.ProductPolicy_Spec type ProductPolicy_Spec struct { - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *ProductPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (policy *ProductPolicy_STATUS) ConvertStatusTo(destination genruntime.Conve return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20220801.ProductPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ProductPolicy{}, &ProductPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen_test.go index 6f5c257ad56..2c7ef8e1195 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_policy_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForProductPolicy(gens map[string]gopter.Gen) { gens["Status"] = ProductPolicy_STATUSGenerator() } +func Test_ProductPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductPolicyOperatorSpec runs a test to see if a specific instance of ProductPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductPolicyOperatorSpec instances for property testing - lazily instantiated by +// ProductPolicyOperatorSpecGenerator() +var productPolicyOperatorSpecGenerator gopter.Gen + +// ProductPolicyOperatorSpecGenerator returns a generator of ProductPolicyOperatorSpec instances for property testing. +func ProductPolicyOperatorSpecGenerator() gopter.Gen { + if productPolicyOperatorSpecGenerator != nil { + return productPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicyOperatorSpec{}), generators) + + return productPolicyOperatorSpecGenerator +} + func Test_ProductPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -186,6 +241,9 @@ func RunJSONSerializationTestForProductPolicy_Spec(subject ProductPolicy_Spec) s var productPolicy_SpecGenerator gopter.Gen // ProductPolicy_SpecGenerator returns a generator of ProductPolicy_Spec instances for property testing. +// We first initialize productPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductPolicy_SpecGenerator() gopter.Gen { if productPolicy_SpecGenerator != nil { return productPolicy_SpecGenerator @@ -195,6 +253,12 @@ func ProductPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForProductPolicy_Spec(generators) + productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + return productPolicy_SpecGenerator } @@ -204,3 +268,8 @@ func AddIndependentPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopte gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProductPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/product_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/product_types_gen.go index 34b5391f66d..a7b7a94866b 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (product *Product) SetConditions(conditions conditions.Conditions) { product.Status.Conditions = conditions } +var _ configmaps.Exporter = &Product{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (product *Product) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Product{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (product *Product) SecretDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Product{} // AzureName returns the Azure name of the resource @@ -145,10 +168,11 @@ type Product_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + OperatorSpec *ProductOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -218,6 +242,14 @@ func (product *Product_STATUS) ConvertStatusTo(destination genruntime.Convertibl return destination.ConvertStatusFrom(product) } +// Storage version of v1api20220801.ProductOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&Product{}, &ProductList{}) } diff --git a/v2/api/apimanagement/v1api20220801/storage/product_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/product_types_gen_test.go index b793c39418d..2afd58ab3d6 100644 --- a/v2/api/apimanagement/v1api20220801/storage/product_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/product_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForProduct(gens map[string]gopter.Gen) { gens["Status"] = Product_STATUSGenerator() } +func Test_ProductOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductOperatorSpec runs a test to see if a specific instance of ProductOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductOperatorSpec instances for property testing - lazily instantiated by +// ProductOperatorSpecGenerator() +var productOperatorSpecGenerator gopter.Gen + +// ProductOperatorSpecGenerator returns a generator of ProductOperatorSpec instances for property testing. +func ProductOperatorSpecGenerator() gopter.Gen { + if productOperatorSpecGenerator != nil { + return productOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductOperatorSpec{}), generators) + + return productOperatorSpecGenerator +} + func Test_Product_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -190,6 +245,9 @@ func RunJSONSerializationTestForProduct_Spec(subject Product_Spec) string { var product_SpecGenerator gopter.Gen // Product_SpecGenerator returns a generator of Product_Spec instances for property testing. +// We first initialize product_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Product_SpecGenerator() gopter.Gen { if product_SpecGenerator != nil { return product_SpecGenerator @@ -199,6 +257,12 @@ func Product_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProduct_Spec(generators) product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProduct_Spec(generators) + AddRelatedPropertyGeneratorsForProduct_Spec(generators) + product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + return product_SpecGenerator } @@ -214,3 +278,8 @@ func AddIndependentPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) gens["SubscriptionsLimit"] = gen.PtrOf(gen.Int()) gens["Terms"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProduct_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20220801/storage/service_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/service_types_gen.go index 43bb35136db..1795f0583b1 100644 --- a/v2/api/apimanagement/v1api20220801/storage/service_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (service *Service) SetConditions(conditions conditions.Conditions) { service.Status.Conditions = conditions } +var _ configmaps.Exporter = &Service{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *Service) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Service{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *Service) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Service{} // AzureName returns the Azure name of the resource @@ -155,6 +178,7 @@ type Service_Spec struct { Location *string `json:"location,omitempty"` NatGatewayState *string `json:"natGatewayState,omitempty"` NotificationSenderEmail *string `json:"notificationSenderEmail,omitempty"` + OperatorSpec *ServiceOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -412,6 +436,14 @@ type RemotePrivateEndpointConnectionWrapper_STATUS struct { Type *string `json:"type,omitempty"` } +// Storage version of v1api20220801.ServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220801.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/apimanagement/v1api20220801/storage/service_types_gen_test.go b/v2/api/apimanagement/v1api20220801/storage/service_types_gen_test.go index f00708f1abc..28877a331f7 100644 --- a/v2/api/apimanagement/v1api20220801/storage/service_types_gen_test.go +++ b/v2/api/apimanagement/v1api20220801/storage/service_types_gen_test.go @@ -1289,6 +1289,61 @@ func AddRelatedPropertyGeneratorsForService(gens map[string]gopter.Gen) { gens["Status"] = Service_STATUSGenerator() } +func Test_ServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServiceOperatorSpec runs a test to see if a specific instance of ServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServiceOperatorSpec instances for property testing - lazily instantiated by +// ServiceOperatorSpecGenerator() +var serviceOperatorSpecGenerator gopter.Gen + +// ServiceOperatorSpecGenerator returns a generator of ServiceOperatorSpec instances for property testing. +func ServiceOperatorSpecGenerator() gopter.Gen { + if serviceOperatorSpecGenerator != nil { + return serviceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serviceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServiceOperatorSpec{}), generators) + + return serviceOperatorSpecGenerator +} + func Test_Service_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1499,6 +1554,7 @@ func AddRelatedPropertyGeneratorsForService_Spec(gens map[string]gopter.Gen) { gens["Certificates"] = gen.SliceOf(CertificateConfigurationGenerator()) gens["HostnameConfigurations"] = gen.SliceOf(HostnameConfigurationGenerator()) gens["Identity"] = gen.PtrOf(ApiManagementServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServiceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(ApiManagementServiceSkuPropertiesGenerator()) gens["VirtualNetworkConfiguration"] = gen.PtrOf(VirtualNetworkConfigurationGenerator()) } diff --git a/v2/api/apimanagement/v1api20220801/storage/structure.txt b/v2/api/apimanagement/v1api20220801/storage/structure.txt index 5e48e632961..e8bcdeaedd8 100644 --- a/v2/api/apimanagement/v1api20220801/storage/structure.txt +++ b/v2/api/apimanagement/v1api20220801/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-08-01" Api: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (29 properties) +├── Spec: Object (30 properties) │ ├── APIVersion: *string │ ├── ApiRevision: *string │ ├── ApiRevisionDescription: *string @@ -52,6 +52,10 @@ Api: Resource │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Url: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Path: *string @@ -135,10 +139,14 @@ Api: Resource └── Type: *string ApiVersionSet: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Description: *string │ ├── DisplayName: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -158,7 +166,7 @@ ApiVersionSet: Resource └── VersioningScheme: *string AuthorizationProvider: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── DisplayName: *string │ ├── IdentityProvider: *string @@ -169,6 +177,10 @@ AuthorizationProvider: Resource │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── RedirectUrl: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -189,10 +201,14 @@ AuthorizationProvider: Resource └── Type: *string AuthorizationProvidersAuthorization: Resource ├── Owner: apimanagement/v1api20220801.AuthorizationProvider -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AuthorizationType: *string │ ├── AzureName: string │ ├── Oauth2GrantType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Parameters: *genruntime.SecretMapReference @@ -213,10 +229,14 @@ AuthorizationProvidersAuthorization: Resource └── Type: *string AuthorizationProvidersAuthorizationsAccessPolicy: Resource ├── Owner: apimanagement/v1api20220801.AuthorizationProvidersAuthorization -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── ObjectId: *string │ ├── ObjectIdFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -232,7 +252,7 @@ AuthorizationProvidersAuthorizationsAccessPolicy: Resource └── Type: *string Backend: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── Credentials: *Object (6 properties) │ │ ├── Authorization: *Object (3 properties) @@ -245,6 +265,10 @@ Backend: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Query: map[string]string[] │ ├── Description: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (2 properties) @@ -318,7 +342,7 @@ Backend: Resource └── Url: *string NamedValue: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── DisplayName: *string │ ├── KeyVault: *Object (4 properties) @@ -326,6 +350,10 @@ NamedValue: Resource │ │ ├── IdentityClientIdFromConfig: *genruntime.ConfigMapReference │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── SecretIdentifier: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -353,8 +381,12 @@ NamedValue: Resource └── Value: *string Policy: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -369,10 +401,14 @@ Policy: Resource └── Value: *string PolicyFragment: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Description: *string │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -388,11 +424,15 @@ PolicyFragment: Resource └── Value: *string Product: Resource ├── Owner: apimanagement/v1api20220801.Service -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── ApprovalRequired: *bool │ ├── AzureName: string │ ├── Description: *string │ ├── DisplayName: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -415,8 +455,12 @@ Product: Resource └── Type: *string ProductApi: Resource ├── Owner: apimanagement/v1api20220801.Product -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -425,8 +469,12 @@ ProductApi: Resource └── PropertyBag: genruntime.PropertyBag ProductPolicy: Resource ├── Owner: apimanagement/v1api20220801.Product -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -441,7 +489,7 @@ ProductPolicy: Resource └── Value: *string Service: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (25 properties) +├── Spec: Object (26 properties) │ ├── AdditionalLocations: Object (8 properties)[] │ │ ├── DisableGateway: *bool │ │ ├── Location: *string @@ -506,6 +554,10 @@ Service: Resource │ ├── Location: *string │ ├── NatGatewayState: *string │ ├── NotificationSenderEmail: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -654,8 +706,10 @@ Subscription: Resource │ ├── AllowTracing: *bool │ ├── AzureName: string │ ├── DisplayName: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── PrimaryKey: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/apimanagement/v1api20220801/storage/subscription_types_gen.go b/v2/api/apimanagement/v1api20220801/storage/subscription_types_gen.go index b1f7e5ea597..ff1b4939277 100644 --- a/v2/api/apimanagement/v1api20220801/storage/subscription_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/storage/subscription_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (subscription *Subscription) SetConditions(conditions conditions.Conditions subscription.Status.Conditions = conditions } +var _ configmaps.Exporter = &Subscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *Subscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Subscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *Subscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Subscription{} // AzureName returns the Azure name of the resource @@ -228,8 +251,10 @@ func (subscription *Subscription_STATUS) ConvertStatusTo(destination genruntime. // Storage version of v1api20220801.SubscriptionOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SubscriptionOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20220801.SubscriptionOperatorSecrets diff --git a/v2/api/apimanagement/v1api20220801/storage/zz_generated.deepcopy.go b/v2/api/apimanagement/v1api20220801/storage/zz_generated.deepcopy.go index fabdaee873f..30d20bb6c03 100644 --- a/v2/api/apimanagement/v1api20220801/storage/zz_generated.deepcopy.go +++ b/v2/api/apimanagement/v1api20220801/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -525,6 +526,50 @@ func (in *ApiManagementServiceSkuProperties_STATUS) DeepCopy() *ApiManagementSer return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiOperatorSpec) DeepCopyInto(out *ApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiOperatorSpec. +func (in *ApiOperatorSpec) DeepCopy() *ApiOperatorSpec { + if in == nil { + return nil + } + out := new(ApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionConstraint) DeepCopyInto(out *ApiVersionConstraint) { *out = *in @@ -742,6 +787,50 @@ func (in *ApiVersionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiVersionSetOperatorSpec) DeepCopyInto(out *ApiVersionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiVersionSetOperatorSpec. +func (in *ApiVersionSetOperatorSpec) DeepCopy() *ApiVersionSetOperatorSpec { + if in == nil { + return nil + } + out := new(ApiVersionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionSet_STATUS) DeepCopyInto(out *ApiVersionSet_STATUS) { *out = *in @@ -824,6 +913,11 @@ func (in *ApiVersionSet_Spec) DeepCopyInto(out *ApiVersionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiVersionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1085,6 +1179,11 @@ func (in *Api_Spec) DeepCopyInto(out *Api_Spec) { *out = new(ApiLicenseInformation) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1506,6 +1605,50 @@ func (in *AuthorizationProviderOAuth2Settings_STATUS) DeepCopy() *AuthorizationP return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProviderOperatorSpec) DeepCopyInto(out *AuthorizationProviderOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProviderOperatorSpec. +func (in *AuthorizationProviderOperatorSpec) DeepCopy() *AuthorizationProviderOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProviderOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvider_STATUS) DeepCopyInto(out *AuthorizationProvider_STATUS) { *out = *in @@ -1583,6 +1726,11 @@ func (in *AuthorizationProvider_Spec) DeepCopyInto(out *AuthorizationProvider_Sp *out = new(AuthorizationProviderOAuth2Settings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProviderOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1666,6 +1814,50 @@ func (in *AuthorizationProvidersAuthorizationList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationOperatorSpec. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorization_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorization_STATUS) { *out = *in @@ -1750,6 +1942,11 @@ func (in *AuthorizationProvidersAuthorization_Spec) DeepCopyInto(out *Authorizat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1838,6 +2035,50 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicyList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) { *out = *in @@ -1905,6 +2146,11 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) DeepCopyInto(ou *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2200,6 +2446,50 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendOperatorSpec) DeepCopyInto(out *BackendOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendOperatorSpec. +func (in *BackendOperatorSpec) DeepCopy() *BackendOperatorSpec { + if in == nil { + return nil + } + out := new(BackendOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendProperties) DeepCopyInto(out *BackendProperties) { *out = *in @@ -2597,6 +2887,11 @@ func (in *Backend_Spec) DeepCopyInto(out *Backend_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackendOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3148,6 +3443,50 @@ func (in *NamedValueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedValueOperatorSpec) DeepCopyInto(out *NamedValueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedValueOperatorSpec. +func (in *NamedValueOperatorSpec) DeepCopy() *NamedValueOperatorSpec { + if in == nil { + return nil + } + out := new(NamedValueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamedValue_STATUS) DeepCopyInto(out *NamedValue_STATUS) { *out = *in @@ -3230,6 +3569,11 @@ func (in *NamedValue_Spec) DeepCopyInto(out *NamedValue_Spec) { *out = new(KeyVaultContractCreateProperties) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamedValueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3483,6 +3827,50 @@ func (in *PolicyFragmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyFragmentOperatorSpec) DeepCopyInto(out *PolicyFragmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyFragmentOperatorSpec. +func (in *PolicyFragmentOperatorSpec) DeepCopy() *PolicyFragmentOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyFragmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyFragment_STATUS) DeepCopyInto(out *PolicyFragment_STATUS) { *out = *in @@ -3555,6 +3943,11 @@ func (in *PolicyFragment_Spec) DeepCopyInto(out *PolicyFragment_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyFragmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3616,6 +4009,50 @@ func (in *PolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyOperatorSpec) DeepCopyInto(out *PolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyOperatorSpec. +func (in *PolicyOperatorSpec) DeepCopy() *PolicyOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy_STATUS) DeepCopyInto(out *Policy_STATUS) { *out = *in @@ -3678,6 +4115,11 @@ func (in *Policy_Spec) DeepCopyInto(out *Policy_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3830,6 +4272,50 @@ func (in *ProductApiList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductApiOperatorSpec) DeepCopyInto(out *ProductApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductApiOperatorSpec. +func (in *ProductApiOperatorSpec) DeepCopy() *ProductApiOperatorSpec { + if in == nil { + return nil + } + out := new(ProductApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_STATUS) DeepCopyInto(out *ProductApi_STATUS) { *out = *in @@ -3862,6 +4348,11 @@ func (in *ProductApi_STATUS) DeepCopy() *ProductApi_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_Spec) DeepCopyInto(out *ProductApi_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3918,6 +4409,50 @@ func (in *ProductList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductOperatorSpec) DeepCopyInto(out *ProductOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductOperatorSpec. +func (in *ProductOperatorSpec) DeepCopy() *ProductOperatorSpec { + if in == nil { + return nil + } + out := new(ProductOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy) DeepCopyInto(out *ProductPolicy) { *out = *in @@ -3977,6 +4512,50 @@ func (in *ProductPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductPolicyOperatorSpec) DeepCopyInto(out *ProductPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductPolicyOperatorSpec. +func (in *ProductPolicyOperatorSpec) DeepCopy() *ProductPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ProductPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy_STATUS) DeepCopyInto(out *ProductPolicy_STATUS) { *out = *in @@ -4039,6 +4618,11 @@ func (in *ProductPolicy_Spec) DeepCopyInto(out *ProductPolicy_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4165,6 +4749,11 @@ func (in *Product_Spec) DeepCopyInto(out *Product_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4325,6 +4914,50 @@ func (in *ServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceOperatorSpec) DeepCopyInto(out *ServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceOperatorSpec. +func (in *ServiceOperatorSpec) DeepCopy() *ServiceOperatorSpec { + if in == nil { + return nil + } + out := new(ServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service_STATUS) DeepCopyInto(out *Service_STATUS) { *out = *in @@ -4632,6 +5265,11 @@ func (in *Service_Spec) DeepCopyInto(out *Service_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4866,6 +5504,17 @@ func (in *SubscriptionOperatorSecrets) DeepCopy() *SubscriptionOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -4873,6 +5522,17 @@ func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SubscriptionOperatorSecrets) diff --git a/v2/api/apimanagement/v1api20220801/structure.txt b/v2/api/apimanagement/v1api20220801/structure.txt index c5e797822c2..876d7f44918 100644 --- a/v2/api/apimanagement/v1api20220801/structure.txt +++ b/v2/api/apimanagement/v1api20220801/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-08-01" Api: Resource ├── Owner: Service -├── Spec: Object (27 properties) +├── Spec: Object (28 properties) │ ├── APIVersion: Validated<*string> (1 rule) │ │ └── Rule 0: MaxLength: 100 │ ├── ApiRevision: Validated<*string> (2 rules) @@ -76,6 +76,9 @@ Api: Resource │ ├── License: *Object (2 properties) │ │ ├── Name: *string │ │ └── Url: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Path: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 400 @@ -174,7 +177,7 @@ Api: Resource └── Type: *string ApiVersionSet: Resource ├── Owner: Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ ├── Rule 1: MinLength: 1 @@ -183,6 +186,9 @@ ApiVersionSet: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── VersionHeaderName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 @@ -209,7 +215,7 @@ ApiVersionSet: Resource └── "Segment" AuthorizationProvider: Resource ├── Owner: Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ ├── Rule 1: MinLength: 1 @@ -223,6 +229,9 @@ AuthorizationProvider: Resource │ │ │ ├── AuthorizationCode: *genruntime.SecretMapReference │ │ │ └── ClientCredentials: *genruntime.SecretMapReference │ │ └── RedirectUrl: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Conditions: conditions.Condition[] @@ -238,7 +247,7 @@ AuthorizationProvider: Resource └── Type: *string AuthorizationProvidersAuthorization: Resource ├── Owner: AuthorizationProvider -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AuthorizationType: *Enum (1 value) │ │ └── "OAuth2" │ ├── AzureName: Validated (3 rules) @@ -248,6 +257,9 @@ AuthorizationProvidersAuthorization: Resource │ ├── Oauth2GrantType: *Enum (2 values) │ │ ├── "AuthorizationCode" │ │ └── "ClientCredentials" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Parameters: *genruntime.SecretMapReference └── Status: Object (9 properties) @@ -267,13 +279,16 @@ AuthorizationProvidersAuthorization: Resource └── Type: *string AuthorizationProvidersAuthorizationsAccessPolicy: Resource ├── Owner: AuthorizationProvidersAuthorization -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^[^*#&+:<>?]+$" │ ├── ObjectId: *string │ ├── ObjectIdFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── TenantId: *string │ └── TenantIdFromConfig: *genruntime.ConfigMapReference @@ -286,7 +301,7 @@ AuthorizationProvidersAuthorizationsAccessPolicy: Resource └── Type: *string Backend: Resource ├── Owner: Service -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ └── Rule 1: MinLength: 1 @@ -307,6 +322,9 @@ Backend: Resource │ ├── Description: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 2000 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (1 property) │ │ └── ServiceFabricCluster: *Object (6 properties) @@ -375,7 +393,7 @@ Backend: Resource └── Url: *string NamedValue: Resource ├── Owner: Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ └── Rule 1: Pattern: "^[^*#&+:<>?]+$" @@ -387,6 +405,9 @@ NamedValue: Resource │ │ ├── IdentityClientId: *string │ │ ├── IdentityClientIdFromConfig: *genruntime.ConfigMapReference │ │ └── SecretIdentifier: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Secret: *bool │ ├── Tags: Validated (1 rule) @@ -411,12 +432,15 @@ NamedValue: Resource └── Value: *string Policy: Resource ├── Owner: Service -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── Format: *Enum (4 values) │ │ ├── "rawxml" │ │ ├── "rawxml-link" │ │ ├── "xml" │ │ └── "xml-link" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (6 properties) @@ -432,7 +456,7 @@ Policy: Resource └── Value: *string PolicyFragment: Resource ├── Owner: Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ ├── Rule 1: MinLength: 1 @@ -443,6 +467,9 @@ PolicyFragment: Resource │ ├── Format: *Enum (2 values) │ │ ├── "rawxml" │ │ └── "xml" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (7 properties) @@ -457,7 +484,7 @@ PolicyFragment: Resource └── Value: *string Product: Resource ├── Owner: Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── ApprovalRequired: *bool │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 256 @@ -468,6 +495,9 @@ Product: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 300 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── State: *Enum (2 values) │ │ ├── "notPublished" @@ -491,22 +521,28 @@ Product: Resource └── Type: *string ProductApi: Resource ├── Owner: Product -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^[^*#&+:<>?]+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (1 property) └── Conditions: conditions.Condition[] ProductPolicy: Resource ├── Owner: Product -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── Format: *Enum (4 values) │ │ ├── "rawxml" │ │ ├── "rawxml-link" │ │ ├── "xml" │ │ └── "xml-link" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (6 properties) @@ -522,7 +558,7 @@ ProductPolicy: Resource └── Value: *string Service: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (23 properties) +├── Spec: Object (24 properties) │ ├── AdditionalLocations: Object (7 properties)[] │ │ ├── DisableGateway: *bool │ │ ├── Location: *string @@ -609,6 +645,9 @@ Service: Resource │ │ └── "Enabled" │ ├── NotificationSenderEmail: Validated<*string> (1 rule) │ │ └── Rule 0: MaxLength: 100 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicIpAddressReference: *genruntime.ResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) @@ -811,7 +850,9 @@ Subscription: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 │ │ └── Rule 1: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── PrimaryKey: *genruntime.SecretDestination │ │ └── SecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/apimanagement/v1api20220801/subscription_types_gen.go b/v2/api/apimanagement/v1api20220801/subscription_types_gen.go index c64f6adee77..9f90338ba88 100644 --- a/v2/api/apimanagement/v1api20220801/subscription_types_gen.go +++ b/v2/api/apimanagement/v1api20220801/subscription_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (subscription *Subscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the Subscription resource func (subscription *Subscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &Subscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *Subscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Subscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *Subscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Subscription{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +233,7 @@ func (subscription *Subscription) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (subscription *Subscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -232,7 +254,18 @@ func (subscription *Subscription) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return subscription.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *Subscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -254,14 +287,14 @@ func (subscription *Subscription) validateSecretDestinations() (admission.Warnin if subscription.Spec.OperatorSpec == nil { return nil, nil } - if subscription.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - subscription.Spec.OperatorSpec.Secrets.PrimaryKey, - subscription.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if subscription.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + subscription.Spec.OperatorSpec.Secrets.PrimaryKey, + subscription.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(subscription, toValidate, subscription.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1237,6 +1270,12 @@ var subscriptionCreateParameterProperties_State_Values = map[string]Subscription // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` } @@ -1244,6 +1283,42 @@ type SubscriptionOperatorSpec struct { // AssignProperties_From_SubscriptionOperatorSpec populates our SubscriptionOperatorSpec from the provided source SubscriptionOperatorSpec func (operator *SubscriptionOperatorSpec) AssignProperties_From_SubscriptionOperatorSpec(source *storage.SubscriptionOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret SubscriptionOperatorSecrets @@ -1265,6 +1340,42 @@ func (operator *SubscriptionOperatorSpec) AssignProperties_To_SubscriptionOperat // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.SubscriptionOperatorSecrets diff --git a/v2/api/apimanagement/v1api20220801/zz_generated.deepcopy.go b/v2/api/apimanagement/v1api20220801/zz_generated.deepcopy.go index 407a6ef84ca..c0e2a8908a6 100644 --- a/v2/api/apimanagement/v1api20220801/zz_generated.deepcopy.go +++ b/v2/api/apimanagement/v1api20220801/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220801 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -446,6 +447,43 @@ func (in *ApiManagementServiceSkuProperties_STATUS) DeepCopy() *ApiManagementSer return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiOperatorSpec) DeepCopyInto(out *ApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiOperatorSpec. +func (in *ApiOperatorSpec) DeepCopy() *ApiOperatorSpec { + if in == nil { + return nil + } + out := new(ApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionConstraint) DeepCopyInto(out *ApiVersionConstraint) { *out = *in @@ -635,6 +673,43 @@ func (in *ApiVersionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiVersionSetOperatorSpec) DeepCopyInto(out *ApiVersionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiVersionSetOperatorSpec. +func (in *ApiVersionSetOperatorSpec) DeepCopy() *ApiVersionSetOperatorSpec { + if in == nil { + return nil + } + out := new(ApiVersionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionSet_STATUS) DeepCopyInto(out *ApiVersionSet_STATUS) { *out = *in @@ -710,6 +785,11 @@ func (in *ApiVersionSet_Spec) DeepCopyInto(out *ApiVersionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiVersionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -957,6 +1037,11 @@ func (in *Api_Spec) DeepCopyInto(out *Api_Spec) { *out = new(ApiLicenseInformation) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1315,6 +1400,43 @@ func (in *AuthorizationProviderOAuth2Settings_STATUS) DeepCopy() *AuthorizationP return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProviderOperatorSpec) DeepCopyInto(out *AuthorizationProviderOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProviderOperatorSpec. +func (in *AuthorizationProviderOperatorSpec) DeepCopy() *AuthorizationProviderOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProviderOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvider_STATUS) DeepCopyInto(out *AuthorizationProvider_STATUS) { *out = *in @@ -1385,6 +1507,11 @@ func (in *AuthorizationProvider_Spec) DeepCopyInto(out *AuthorizationProvider_Sp *out = new(AuthorizationProviderOAuth2Settings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProviderOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1461,6 +1588,43 @@ func (in *AuthorizationProvidersAuthorizationList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationOperatorSpec. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorization_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorization_STATUS) { *out = *in @@ -1538,6 +1702,11 @@ func (in *AuthorizationProvidersAuthorization_Spec) DeepCopyInto(out *Authorizat *out = new(AuthorizationContractProperties_Oauth2GrantType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1619,6 +1788,43 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicyList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) { *out = *in @@ -1679,6 +1885,11 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) DeepCopyInto(ou *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1939,6 +2150,43 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendOperatorSpec) DeepCopyInto(out *BackendOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendOperatorSpec. +func (in *BackendOperatorSpec) DeepCopy() *BackendOperatorSpec { + if in == nil { + return nil + } + out := new(BackendOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendProperties) DeepCopyInto(out *BackendProperties) { *out = *in @@ -2273,6 +2521,11 @@ func (in *Backend_Spec) DeepCopyInto(out *Backend_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackendOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2754,6 +3007,43 @@ func (in *NamedValueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedValueOperatorSpec) DeepCopyInto(out *NamedValueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedValueOperatorSpec. +func (in *NamedValueOperatorSpec) DeepCopy() *NamedValueOperatorSpec { + if in == nil { + return nil + } + out := new(NamedValueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamedValue_STATUS) DeepCopyInto(out *NamedValue_STATUS) { *out = *in @@ -2829,6 +3119,11 @@ func (in *NamedValue_Spec) DeepCopyInto(out *NamedValue_Spec) { *out = new(KeyVaultContractCreateProperties) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamedValueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3047,6 +3342,43 @@ func (in *PolicyFragmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyFragmentOperatorSpec) DeepCopyInto(out *PolicyFragmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyFragmentOperatorSpec. +func (in *PolicyFragmentOperatorSpec) DeepCopy() *PolicyFragmentOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyFragmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyFragment_STATUS) DeepCopyInto(out *PolicyFragment_STATUS) { *out = *in @@ -3112,6 +3444,11 @@ func (in *PolicyFragment_Spec) DeepCopyInto(out *PolicyFragment_Spec) { *out = new(PolicyFragmentContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyFragmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3166,6 +3503,43 @@ func (in *PolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyOperatorSpec) DeepCopyInto(out *PolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyOperatorSpec. +func (in *PolicyOperatorSpec) DeepCopy() *PolicyOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy_STATUS) DeepCopyInto(out *Policy_STATUS) { *out = *in @@ -3221,6 +3595,11 @@ func (in *Policy_Spec) DeepCopyInto(out *Policy_Spec) { *out = new(PolicyContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3359,6 +3738,43 @@ func (in *ProductApiList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductApiOperatorSpec) DeepCopyInto(out *ProductApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductApiOperatorSpec. +func (in *ProductApiOperatorSpec) DeepCopy() *ProductApiOperatorSpec { + if in == nil { + return nil + } + out := new(ProductApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_STATUS) DeepCopyInto(out *ProductApi_STATUS) { *out = *in @@ -3384,6 +3800,11 @@ func (in *ProductApi_STATUS) DeepCopy() *ProductApi_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_Spec) DeepCopyInto(out *ProductApi_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3433,6 +3854,43 @@ func (in *ProductList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductOperatorSpec) DeepCopyInto(out *ProductOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductOperatorSpec. +func (in *ProductOperatorSpec) DeepCopy() *ProductOperatorSpec { + if in == nil { + return nil + } + out := new(ProductOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy) DeepCopyInto(out *ProductPolicy) { *out = *in @@ -3492,6 +3950,43 @@ func (in *ProductPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductPolicyOperatorSpec) DeepCopyInto(out *ProductPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductPolicyOperatorSpec. +func (in *ProductPolicyOperatorSpec) DeepCopy() *ProductPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ProductPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy_STATUS) DeepCopyInto(out *ProductPolicy_STATUS) { *out = *in @@ -3547,6 +4042,11 @@ func (in *ProductPolicy_Spec) DeepCopyInto(out *ProductPolicy_Spec) { *out = new(PolicyContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3659,6 +4159,11 @@ func (in *Product_Spec) DeepCopyInto(out *Product_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3805,6 +4310,43 @@ func (in *ServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceOperatorSpec) DeepCopyInto(out *ServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceOperatorSpec. +func (in *ServiceOperatorSpec) DeepCopy() *ServiceOperatorSpec { + if in == nil { + return nil + } + out := new(ServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service_STATUS) DeepCopyInto(out *Service_STATUS) { *out = *in @@ -4105,6 +4647,11 @@ func (in *Service_Spec) DeepCopyInto(out *Service_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4311,6 +4858,28 @@ func (in *SubscriptionOperatorSecrets) DeepCopy() *SubscriptionOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SubscriptionOperatorSecrets) diff --git a/v2/api/apimanagement/v1api20230501preview/api_types_gen.go b/v2/api/apimanagement/v1api20230501preview/api_types_gen.go index d68134e3fb2..a3de0c441dc 100644 --- a/v2/api/apimanagement/v1api20230501preview/api_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/api_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -103,6 +106,26 @@ func (api *Api) defaultAzureName() { // defaultImpl applies the code generated defaults to the Api resource func (api *Api) defaultImpl() { api.defaultAzureName() } +var _ configmaps.Exporter = &Api{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (api *Api) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Api{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (api *Api) SecretDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Api{} // AzureName returns the Azure name of the resource @@ -211,7 +234,7 @@ func (api *Api) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (api *Api) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){api.validateResourceReferences, api.validateOwnerReference} + return []func() (admission.Warnings, error){api.validateResourceReferences, api.validateOwnerReference, api.validateSecretDestinations, api.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (api *Api) updateValidations() []func(old runtime.Object) (admission.Warnin func(old runtime.Object) (admission.Warnings, error) { return api.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return api.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return api.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (api *Api) validateConfigMapDestinations() (admission.Warnings, error) { + if api.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(api, nil, api.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (api *Api) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (api *Api) validateSecretDestinations() (admission.Warnings, error) { + if api.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(api, nil, api.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (api *Api) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Api) @@ -389,6 +434,10 @@ type Api_Spec struct { // License: License information for the API. License *ApiLicenseInformation `json:"license,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApiOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -779,6 +828,8 @@ func (api *Api_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, a } } + // no assignment for property "OperatorSpec" + // Set property "Owner": api.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1077,6 +1128,18 @@ func (api *Api_Spec) AssignProperties_From_Api_Spec(source *storage.Api_Spec) er api.License = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiOperatorSpec + err := operatorSpec.AssignProperties_From_ApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiOperatorSpec() to populate field OperatorSpec") + } + api.OperatorSpec = &operatorSpec + } else { + api.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1313,6 +1376,18 @@ func (api *Api_Spec) AssignProperties_To_Api_Spec(destination *storage.Api_Spec) destination.License = nil } + // OperatorSpec + if api.OperatorSpec != nil { + var operatorSpec storage.ApiOperatorSpec + err := api.OperatorSpec.AssignProperties_To_ApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = api.OriginalVersion() @@ -2788,6 +2863,110 @@ func (information *ApiLicenseInformation_STATUS) AssignProperties_To_ApiLicenseI return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiOperatorSpec populates our ApiOperatorSpec from the provided source ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_From_ApiOperatorSpec(source *storage.ApiOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApiOperatorSpec populates the provided destination ApiOperatorSpec from our ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_To_ApiOperatorSpec(destination *storage.ApiOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An API Version Set contains the common configuration for a set of API Versions relating type ApiVersionSetContractDetails struct { // Description: Description of API Version Set. diff --git a/v2/api/apimanagement/v1api20230501preview/api_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/api_types_gen_test.go index 08c5310de87..6d0f94f95f3 100644 --- a/v2/api/apimanagement/v1api20230501preview/api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/api_types_gen_test.go @@ -687,6 +687,102 @@ func AddIndependentPropertyGeneratorsForApiLicenseInformation_STATUS(gens map[st gens["Url"] = gen.PtrOf(gen.AlphaString()) } +func Test_ApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiOperatorSpec to ApiOperatorSpec via AssignProperties_To_ApiOperatorSpec & AssignProperties_From_ApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiOperatorSpec tests if a specific instance of ApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ApiOperatorSpec + err := copied.AssignProperties_To_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiOperatorSpec + err = actual.AssignProperties_From_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiOperatorSpec runs a test to see if a specific instance of ApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiOperatorSpec instances for property testing - lazily instantiated by ApiOperatorSpecGenerator() +var apiOperatorSpecGenerator gopter.Gen + +// ApiOperatorSpecGenerator returns a generator of ApiOperatorSpec instances for property testing. +func ApiOperatorSpecGenerator() gopter.Gen { + if apiOperatorSpecGenerator != nil { + return apiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiOperatorSpec{}), generators) + + return apiOperatorSpecGenerator +} + func Test_ApiVersionSetContractDetails_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1216,6 +1312,7 @@ func AddRelatedPropertyGeneratorsForApi_Spec(gens map[string]gopter.Gen) { gens["AuthenticationSettings"] = gen.PtrOf(AuthenticationSettingsContractGenerator()) gens["Contact"] = gen.PtrOf(ApiContactInformationGenerator()) gens["License"] = gen.PtrOf(ApiLicenseInformationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApiOperatorSpecGenerator()) gens["SubscriptionKeyParameterNames"] = gen.PtrOf(SubscriptionKeyParameterNamesContractGenerator()) gens["WsdlSelector"] = gen.PtrOf(ApiCreateOrUpdateProperties_WsdlSelectorGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen.go b/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen.go index 48be3990b7b..64f0f8098f6 100644 --- a/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (versionSet *ApiVersionSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the ApiVersionSet resource func (versionSet *ApiVersionSet) defaultImpl() { versionSet.defaultAzureName() } +var _ configmaps.Exporter = &ApiVersionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (versionSet *ApiVersionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApiVersionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (versionSet *ApiVersionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ApiVersionSet{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (versionSet *ApiVersionSet) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (versionSet *ApiVersionSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){versionSet.validateResourceReferences, versionSet.validateOwnerReference} + return []func() (admission.Warnings, error){versionSet.validateResourceReferences, versionSet.validateOwnerReference, versionSet.validateSecretDestinations, versionSet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,9 +254,23 @@ func (versionSet *ApiVersionSet) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return versionSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return versionSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return versionSet.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (versionSet *ApiVersionSet) validateConfigMapDestinations() (admission.Warnings, error) { + if versionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(versionSet, nil, versionSet.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (versionSet *ApiVersionSet) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(versionSet) @@ -248,6 +285,14 @@ func (versionSet *ApiVersionSet) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (versionSet *ApiVersionSet) validateSecretDestinations() (admission.Warnings, error) { + if versionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(versionSet, nil, versionSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (versionSet *ApiVersionSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ApiVersionSet) @@ -346,6 +391,10 @@ type ApiVersionSet_Spec struct { // DisplayName: Name of API Version Set DisplayName *string `json:"displayName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApiVersionSetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -445,6 +494,8 @@ func (versionSet *ApiVersionSet_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": versionSet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -551,6 +602,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_From_ApiVersionSet_Spec(s versionSet.DisplayName = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiVersionSetOperatorSpec + err := operatorSpec.AssignProperties_From_ApiVersionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + versionSet.OperatorSpec = &operatorSpec + } else { + versionSet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -607,6 +670,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_To_ApiVersionSet_Spec(des destination.DisplayName = nil } + // OperatorSpec + if versionSet.OperatorSpec != nil { + var operatorSpec storage.ApiVersionSetOperatorSpec + err := versionSet.OperatorSpec.AssignProperties_To_ApiVersionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = versionSet.OriginalVersion() @@ -947,6 +1022,110 @@ var apiVersionSetContractProperties_VersioningScheme_STATUS_Values = map[string] "segment": ApiVersionSetContractProperties_VersioningScheme_STATUS_Segment, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiVersionSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiVersionSetOperatorSpec populates our ApiVersionSetOperatorSpec from the provided source ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_From_ApiVersionSetOperatorSpec(source *storage.ApiVersionSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApiVersionSetOperatorSpec populates the provided destination ApiVersionSetOperatorSpec from our ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_To_ApiVersionSetOperatorSpec(destination *storage.ApiVersionSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ApiVersionSet{}, &ApiVersionSetList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen_test.go index 4f82a50015a..7929803c646 100644 --- a/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/api_version_set_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForApiVersionSet(gens map[string]gopter.Gen) { gens["Status"] = ApiVersionSet_STATUSGenerator() } +func Test_ApiVersionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiVersionSetOperatorSpec to ApiVersionSetOperatorSpec via AssignProperties_To_ApiVersionSetOperatorSpec & AssignProperties_From_ApiVersionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiVersionSetOperatorSpec tests if a specific instance of ApiVersionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ApiVersionSetOperatorSpec + err := copied.AssignProperties_To_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiVersionSetOperatorSpec + err = actual.AssignProperties_From_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiVersionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiVersionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiVersionSetOperatorSpec runs a test to see if a specific instance of ApiVersionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiVersionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiVersionSetOperatorSpec instances for property testing - lazily instantiated by +// ApiVersionSetOperatorSpecGenerator() +var apiVersionSetOperatorSpecGenerator gopter.Gen + +// ApiVersionSetOperatorSpecGenerator returns a generator of ApiVersionSetOperatorSpec instances for property testing. +func ApiVersionSetOperatorSpecGenerator() gopter.Gen { + if apiVersionSetOperatorSpecGenerator != nil { + return apiVersionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiVersionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSetOperatorSpec{}), generators) + + return apiVersionSetOperatorSpecGenerator +} + func Test_ApiVersionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForApiVersionSet_Spec(subject ApiVersionSet_Spec) s var apiVersionSet_SpecGenerator gopter.Gen // ApiVersionSet_SpecGenerator returns a generator of ApiVersionSet_Spec instances for property testing. +// We first initialize apiVersionSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApiVersionSet_SpecGenerator() gopter.Gen { if apiVersionSet_SpecGenerator != nil { return apiVersionSet_SpecGenerator @@ -369,6 +469,12 @@ func ApiVersionSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) + AddRelatedPropertyGeneratorsForApiVersionSet_Spec(generators) + apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + return apiVersionSet_SpecGenerator } @@ -381,3 +487,8 @@ func AddIndependentPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopte gens["VersionQueryName"] = gen.PtrOf(gen.AlphaString()) gens["VersioningScheme"] = gen.PtrOf(gen.OneConstOf(ApiVersionSetContractProperties_VersioningScheme_Header, ApiVersionSetContractProperties_VersioningScheme_Query, ApiVersionSetContractProperties_VersioningScheme_Segment)) } + +// AddRelatedPropertyGeneratorsForApiVersionSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApiVersionSetOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen.go b/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen.go index 482e65dba82..6144cfa7cd2 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (provider *AuthorizationProvider) defaultAzureName() { // defaultImpl applies the code generated defaults to the AuthorizationProvider resource func (provider *AuthorizationProvider) defaultImpl() { provider.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvider{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (provider *AuthorizationProvider) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvider{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (provider *AuthorizationProvider) SecretDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvider{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (provider *AuthorizationProvider) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (provider *AuthorizationProvider) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){provider.validateResourceReferences, provider.validateOwnerReference} + return []func() (admission.Warnings, error){provider.validateResourceReferences, provider.validateOwnerReference, provider.validateSecretDestinations, provider.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (provider *AuthorizationProvider) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return provider.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return provider.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return provider.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (provider *AuthorizationProvider) validateConfigMapDestinations() (admission.Warnings, error) { + if provider.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(provider, nil, provider.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (provider *AuthorizationProvider) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (provider *AuthorizationProvider) validateSecretDestinations() (admission.Warnings, error) { + if provider.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(provider, nil, provider.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (provider *AuthorizationProvider) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvider) @@ -347,6 +392,10 @@ type AuthorizationProvider_Spec struct { // Oauth2: OAuth2 settings Oauth2 *AuthorizationProviderOAuth2Settings `json:"oauth2,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProviderOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -438,6 +487,8 @@ func (provider *AuthorizationProvider_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": provider.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -527,6 +578,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_From_AuthorizationP provider.Oauth2 = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProviderOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProviderOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + provider.OperatorSpec = &operatorSpec + } else { + provider.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -570,6 +633,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_To_AuthorizationPro destination.Oauth2 = nil } + // OperatorSpec + if provider.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProviderOperatorSpec + err := provider.OperatorSpec.AssignProperties_To_AuthorizationProviderOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = provider.OriginalVersion() @@ -1048,6 +1123,110 @@ func (settings *AuthorizationProviderOAuth2Settings_STATUS) AssignProperties_To_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProviderOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProviderOperatorSpec populates our AuthorizationProviderOperatorSpec from the provided source AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_From_AuthorizationProviderOperatorSpec(source *storage.AuthorizationProviderOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProviderOperatorSpec populates the provided destination AuthorizationProviderOperatorSpec from our AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_To_AuthorizationProviderOperatorSpec(destination *storage.AuthorizationProviderOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Authorization Provider oauth2 grant types settings type AuthorizationProviderOAuth2GrantTypes struct { // AuthorizationCode: OAuth2 authorization code grant parameters diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen_test.go index 37b58e83022..f5284005185 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_provider_types_gen_test.go @@ -605,6 +605,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProviderOAuth2Settings_STATUS(g gens["GrantTypes"] = gen.PtrOf(AuthorizationProviderOAuth2GrantTypes_STATUSGenerator()) } +func Test_AuthorizationProviderOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProviderOperatorSpec to AuthorizationProviderOperatorSpec via AssignProperties_To_AuthorizationProviderOperatorSpec & AssignProperties_From_AuthorizationProviderOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec tests if a specific instance of AuthorizationProviderOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.AuthorizationProviderOperatorSpec + err := copied.AssignProperties_To_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProviderOperatorSpec + err = actual.AssignProperties_From_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProviderOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProviderOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProviderOperatorSpec runs a test to see if a specific instance of AuthorizationProviderOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProviderOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProviderOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProviderOperatorSpecGenerator() +var authorizationProviderOperatorSpecGenerator gopter.Gen + +// AuthorizationProviderOperatorSpecGenerator returns a generator of AuthorizationProviderOperatorSpec instances for property testing. +func AuthorizationProviderOperatorSpecGenerator() gopter.Gen { + if authorizationProviderOperatorSpecGenerator != nil { + return authorizationProviderOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProviderOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProviderOperatorSpec{}), generators) + + return authorizationProviderOperatorSpecGenerator +} + func Test_AuthorizationProvider_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -843,4 +940,5 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvider_Spec(gens map[stri // AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec(gens map[string]gopter.Gen) { gens["Oauth2"] = gen.PtrOf(AuthorizationProviderOAuth2SettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProviderOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen.go b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen.go index e93eb596036..916fe393cf9 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -107,6 +110,26 @@ func (authorization *AuthorizationProvidersAuthorization) defaultImpl() { authorization.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorization{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authorization *AuthorizationProvidersAuthorization) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorization{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authorization *AuthorizationProvidersAuthorization) SecretDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorization{} // AzureName returns the Azure name of the resource @@ -214,7 +237,7 @@ func (authorization *AuthorizationProvidersAuthorization) ValidateUpdate(old run // createValidations validates the creation of the resource func (authorization *AuthorizationProvidersAuthorization) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){authorization.validateResourceReferences, authorization.validateOwnerReference} + return []func() (admission.Warnings, error){authorization.validateResourceReferences, authorization.validateOwnerReference, authorization.validateSecretDestinations, authorization.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -232,7 +255,21 @@ func (authorization *AuthorizationProvidersAuthorization) updateValidations() [] func(old runtime.Object) (admission.Warnings, error) { return authorization.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return authorization.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return authorization.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (authorization *AuthorizationProvidersAuthorization) validateConfigMapDestinations() (admission.Warnings, error) { + if authorization.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(authorization, nil, authorization.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -249,6 +286,14 @@ func (authorization *AuthorizationProvidersAuthorization) validateResourceRefere return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (authorization *AuthorizationProvidersAuthorization) validateSecretDestinations() (admission.Warnings, error) { + if authorization.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(authorization, nil, authorization.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (authorization *AuthorizationProvidersAuthorization) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvidersAuthorization) @@ -344,6 +389,10 @@ type AuthorizationProvidersAuthorization_Spec struct { // Oauth2GrantType: OAuth2 grant type options Oauth2GrantType *AuthorizationContractProperties_Oauth2GrantType `json:"oauth2grantType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProvidersAuthorizationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -433,6 +482,8 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) PopulateFromARM(o } } + // no assignment for property "OperatorSpec" + // Set property "Owner": authorization.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -519,6 +570,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ authorization.Oauth2GrantType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + authorization.OperatorSpec = &operatorSpec + } else { + authorization.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -563,6 +626,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ destination.Oauth2GrantType = nil } + // OperatorSpec + if authorization.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationOperatorSpec + err := authorization.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = authorization.OriginalVersion() @@ -1014,6 +1089,110 @@ func (error *AuthorizationError_STATUS) AssignProperties_To_AuthorizationError_S return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec populates our AuthorizationProvidersAuthorizationOperatorSpec from the provided source AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationOperatorSpec from our AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorization{}, &AuthorizationProvidersAuthorizationList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen_test.go index 3da419eb007..61085d56aa9 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorization_types_gen_test.go @@ -270,6 +270,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization(gens map gens["Status"] = AuthorizationProvidersAuthorization_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationOperatorSpec to AuthorizationProvidersAuthorizationOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.AuthorizationProvidersAuthorizationOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProvidersAuthorizationOperatorSpecGenerator() +var authorizationProvidersAuthorizationOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorization_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -481,6 +578,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorization_Spec(subject var authorizationProvidersAuthorization_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorization_SpecGenerator returns a generator of AuthorizationProvidersAuthorization_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorization_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorization_SpecGenerator != nil { return authorizationProvidersAuthorization_SpecGenerator @@ -490,6 +590,12 @@ func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + return authorizationProvidersAuthorization_SpecGenerator } @@ -499,3 +605,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec gens["AzureName"] = gen.AlphaString() gens["Oauth2GrantType"] = gen.PtrOf(gen.OneConstOf(AuthorizationContractProperties_Oauth2GrantType_AuthorizationCode, AuthorizationContractProperties_Oauth2GrantType_ClientCredentials)) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen.go index b3a269aa159..e3d129fa668 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -108,6 +110,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorizationsAccessPolicy{} // AzureName returns the Azure name of the resource @@ -215,7 +237,7 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ValidateUpdate(o // createValidations validates the creation of the resource func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations, policy.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -233,12 +255,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) updateValidation func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return policy.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&policy.Spec) @@ -262,6 +298,14 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateResource return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AuthorizationProvidersAuthorizationsAccessPolicy) @@ -360,6 +404,10 @@ type AuthorizationProvidersAuthorizationsAccessPolicy_Spec struct { // ObjectIdFromConfig: The Object Id ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -457,6 +505,8 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) PopulateFro // no assignment for property "ObjectIdFromConfig" + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -548,6 +598,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope policy.ObjectIdFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -593,6 +655,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope destination.ObjectIdFromConfig = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -839,6 +913,110 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) AssignPro return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from the provided source AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorizationsAccessPolicy{}, &AuthorizationProvidersAuthorizationsAccessPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen_test.go index b83c94fe2b7..256e17f1935 100644 --- a/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/authorization_providers_authorizations_access_policy_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPo gens["Status"] = AuthorizationProvidersAuthorizationsAccessPolicy_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec to AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing - lazily +// instantiated by AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() +var authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorizationsAccessPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicy var authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicy_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator != nil { return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator @@ -369,6 +469,12 @@ func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAcce gens["ObjectId"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/backend_types_gen.go b/v2/api/apimanagement/v1api20230501preview/backend_types_gen.go index 07817fe4cfa..a2df3850067 100644 --- a/v2/api/apimanagement/v1api20230501preview/backend_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/backend_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (backend *Backend) defaultAzureName() { // defaultImpl applies the code generated defaults to the Backend resource func (backend *Backend) defaultImpl() { backend.defaultAzureName() } +var _ configmaps.Exporter = &Backend{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (backend *Backend) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Backend{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (backend *Backend) SecretDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Backend{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (backend *Backend) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (backend *Backend) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){backend.validateResourceReferences, backend.validateOwnerReference} + return []func() (admission.Warnings, error){backend.validateResourceReferences, backend.validateOwnerReference, backend.validateSecretDestinations, backend.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (backend *Backend) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return backend.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return backend.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return backend.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (backend *Backend) validateConfigMapDestinations() (admission.Warnings, error) { + if backend.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(backend, nil, backend.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (backend *Backend) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (backend *Backend) validateSecretDestinations() (admission.Warnings, error) { + if backend.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(backend, nil, backend.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (backend *Backend) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Backend) @@ -347,6 +392,10 @@ type Backend_Spec struct { // Description: Backend Description. Description *string `json:"description,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BackendOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -550,6 +599,8 @@ func (backend *Backend_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": backend.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -746,6 +797,18 @@ func (backend *Backend_Spec) AssignProperties_From_Backend_Spec(source *storage. backend.Description = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackendOperatorSpec + err := operatorSpec.AssignProperties_From_BackendOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackendOperatorSpec() to populate field OperatorSpec") + } + backend.OperatorSpec = &operatorSpec + } else { + backend.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -888,6 +951,18 @@ func (backend *Backend_Spec) AssignProperties_To_Backend_Spec(destination *stora destination.Description = nil } + // OperatorSpec + if backend.OperatorSpec != nil { + var operatorSpec storage.BackendOperatorSpec + err := backend.OperatorSpec.AssignProperties_To_BackendOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackendOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = backend.OriginalVersion() @@ -2275,6 +2350,110 @@ func (contract *BackendCredentialsContract_STATUS) AssignProperties_To_BackendCr return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackendOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackendOperatorSpec populates our BackendOperatorSpec from the provided source BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_From_BackendOperatorSpec(source *storage.BackendOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BackendOperatorSpec populates the provided destination BackendOperatorSpec from our BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_To_BackendOperatorSpec(destination *storage.BackendOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Backend pool information type BackendPool struct { // +kubebuilder:validation:MinItems=1 diff --git a/v2/api/apimanagement/v1api20230501preview/backend_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/backend_types_gen_test.go index 338492a6091..87709226733 100644 --- a/v2/api/apimanagement/v1api20230501preview/backend_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/backend_types_gen_test.go @@ -827,6 +827,103 @@ func AddRelatedPropertyGeneratorsForBackendCredentialsContract_STATUS(gens map[s gens["Authorization"] = gen.PtrOf(BackendAuthorizationHeaderCredentials_STATUSGenerator()) } +func Test_BackendOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackendOperatorSpec to BackendOperatorSpec via AssignProperties_To_BackendOperatorSpec & AssignProperties_From_BackendOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackendOperatorSpec tests if a specific instance of BackendOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.BackendOperatorSpec + err := copied.AssignProperties_To_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackendOperatorSpec + err = actual.AssignProperties_From_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackendOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackendOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackendOperatorSpec runs a test to see if a specific instance of BackendOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackendOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackendOperatorSpec instances for property testing - lazily instantiated by +// BackendOperatorSpecGenerator() +var backendOperatorSpecGenerator gopter.Gen + +// BackendOperatorSpecGenerator returns a generator of BackendOperatorSpec instances for property testing. +func BackendOperatorSpecGenerator() gopter.Gen { + if backendOperatorSpecGenerator != nil { + return backendOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backendOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackendOperatorSpec{}), generators) + + return backendOperatorSpecGenerator +} + func Test_BackendPool_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2342,6 +2439,7 @@ func AddIndependentPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) { gens["CircuitBreaker"] = gen.PtrOf(BackendCircuitBreakerGenerator()) gens["Credentials"] = gen.PtrOf(BackendCredentialsContractGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BackendOperatorSpecGenerator()) gens["Pool"] = gen.PtrOf(BackendPoolGenerator()) gens["Properties"] = gen.PtrOf(BackendPropertiesGenerator()) gens["Proxy"] = gen.PtrOf(BackendProxyContractGenerator()) diff --git a/v2/api/apimanagement/v1api20230501preview/named_value_types_gen.go b/v2/api/apimanagement/v1api20230501preview/named_value_types_gen.go index 59be007c938..75b0a30e87a 100644 --- a/v2/api/apimanagement/v1api20230501preview/named_value_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/named_value_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +108,26 @@ func (value *NamedValue) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamedValue resource func (value *NamedValue) defaultImpl() { value.defaultAzureName() } +var _ configmaps.Exporter = &NamedValue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (value *NamedValue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamedValue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (value *NamedValue) SecretDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamedValue{} // AzureName returns the Azure name of the resource @@ -214,7 +236,7 @@ func (value *NamedValue) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (value *NamedValue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){value.validateResourceReferences, value.validateOwnerReference, value.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){value.validateResourceReferences, value.validateOwnerReference, value.validateSecretDestinations, value.validateConfigMapDestinations, value.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -232,12 +254,26 @@ func (value *NamedValue) updateValidations() []func(old runtime.Object) (admissi func(old runtime.Object) (admission.Warnings, error) { return value.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return value.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return value.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return value.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (value *NamedValue) validateConfigMapDestinations() (admission.Warnings, error) { + if value.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(value, nil, value.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (value *NamedValue) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&value.Spec) @@ -261,6 +297,14 @@ func (value *NamedValue) validateResourceReferences() (admission.Warnings, error return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (value *NamedValue) validateSecretDestinations() (admission.Warnings, error) { + if value.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(value, nil, value.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (value *NamedValue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamedValue) @@ -359,6 +403,10 @@ type NamedValue_Spec struct { // KeyVault: KeyVault location details of the namedValue. KeyVault *KeyVaultContractCreateProperties `json:"keyVault,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamedValueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -462,6 +510,8 @@ func (value *NamedValue_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRef } } + // no assignment for property "OperatorSpec" + // Set property "Owner": value.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -574,6 +624,18 @@ func (value *NamedValue_Spec) AssignProperties_From_NamedValue_Spec(source *stor value.KeyVault = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamedValueOperatorSpec + err := operatorSpec.AssignProperties_From_NamedValueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamedValueOperatorSpec() to populate field OperatorSpec") + } + value.OperatorSpec = &operatorSpec + } else { + value.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -643,6 +705,18 @@ func (value *NamedValue_Spec) AssignProperties_To_NamedValue_Spec(destination *s destination.KeyVault = nil } + // OperatorSpec + if value.OperatorSpec != nil { + var operatorSpec storage.NamedValueOperatorSpec + err := value.OperatorSpec.AssignProperties_To_NamedValueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamedValueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = value.OriginalVersion() @@ -1234,6 +1308,110 @@ func (properties *KeyVaultContractProperties_STATUS) AssignProperties_To_KeyVaul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamedValueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamedValueOperatorSpec populates our NamedValueOperatorSpec from the provided source NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_From_NamedValueOperatorSpec(source *storage.NamedValueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamedValueOperatorSpec populates the provided destination NamedValueOperatorSpec from our NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_To_NamedValueOperatorSpec(destination *storage.NamedValueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Issue contract Update Properties. type KeyVaultLastAccessStatusContractProperties_STATUS struct { // Code: Last status code for sync and refresh of secret from key vault. diff --git a/v2/api/apimanagement/v1api20230501preview/named_value_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/named_value_types_gen_test.go index e7774fdddbc..4066c4c1acf 100644 --- a/v2/api/apimanagement/v1api20230501preview/named_value_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/named_value_types_gen_test.go @@ -492,6 +492,103 @@ func AddRelatedPropertyGeneratorsForNamedValue(gens map[string]gopter.Gen) { gens["Status"] = NamedValue_STATUSGenerator() } +func Test_NamedValueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamedValueOperatorSpec to NamedValueOperatorSpec via AssignProperties_To_NamedValueOperatorSpec & AssignProperties_From_NamedValueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamedValueOperatorSpec tests if a specific instance of NamedValueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.NamedValueOperatorSpec + err := copied.AssignProperties_To_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamedValueOperatorSpec + err = actual.AssignProperties_From_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamedValueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamedValueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamedValueOperatorSpec runs a test to see if a specific instance of NamedValueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamedValueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamedValueOperatorSpec instances for property testing - lazily instantiated by +// NamedValueOperatorSpecGenerator() +var namedValueOperatorSpecGenerator gopter.Gen + +// NamedValueOperatorSpecGenerator returns a generator of NamedValueOperatorSpec instances for property testing. +func NamedValueOperatorSpecGenerator() gopter.Gen { + if namedValueOperatorSpecGenerator != nil { + return namedValueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namedValueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamedValueOperatorSpec{}), generators) + + return namedValueOperatorSpecGenerator +} + func Test_NamedValue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -733,4 +830,5 @@ func AddIndependentPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNamedValue_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.Gen) { gens["KeyVault"] = gen.PtrOf(KeyVaultContractCreatePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamedValueOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen.go b/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen.go index f7cd6cabc12..c4d7fb7a2fe 100644 --- a/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (fragment *PolicyFragment) defaultAzureName() { // defaultImpl applies the code generated defaults to the PolicyFragment resource func (fragment *PolicyFragment) defaultImpl() { fragment.defaultAzureName() } +var _ configmaps.Exporter = &PolicyFragment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fragment *PolicyFragment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PolicyFragment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fragment *PolicyFragment) SecretDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PolicyFragment{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (fragment *PolicyFragment) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (fragment *PolicyFragment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){fragment.validateResourceReferences, fragment.validateOwnerReference} + return []func() (admission.Warnings, error){fragment.validateResourceReferences, fragment.validateOwnerReference, fragment.validateSecretDestinations, fragment.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (fragment *PolicyFragment) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return fragment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return fragment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return fragment.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (fragment *PolicyFragment) validateConfigMapDestinations() (admission.Warnings, error) { + if fragment.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(fragment, nil, fragment.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (fragment *PolicyFragment) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (fragment *PolicyFragment) validateSecretDestinations() (admission.Warnings, error) { + if fragment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(fragment, nil, fragment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (fragment *PolicyFragment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PolicyFragment) @@ -345,6 +390,10 @@ type PolicyFragment_Spec struct { // Format: Format of the policy fragment content. Format *PolicyFragmentContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PolicyFragmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -426,6 +475,8 @@ func (fragment *PolicyFragment_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": fragment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -518,6 +569,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_From_PolicyFragment_Spec(s fragment.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyFragmentOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyFragmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + fragment.OperatorSpec = &operatorSpec + } else { + fragment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -557,6 +620,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_To_PolicyFragment_Spec(des destination.Format = nil } + // OperatorSpec + if fragment.OperatorSpec != nil { + var operatorSpec storage.PolicyFragmentOperatorSpec + err := fragment.OperatorSpec.AssignProperties_To_PolicyFragmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = fragment.OriginalVersion() @@ -852,6 +927,110 @@ var policyFragmentContractProperties_Format_STATUS_Values = map[string]PolicyFra "xml": PolicyFragmentContractProperties_Format_STATUS_Xml, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyFragmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyFragmentOperatorSpec populates our PolicyFragmentOperatorSpec from the provided source PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_From_PolicyFragmentOperatorSpec(source *storage.PolicyFragmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PolicyFragmentOperatorSpec populates the provided destination PolicyFragmentOperatorSpec from our PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_To_PolicyFragmentOperatorSpec(destination *storage.PolicyFragmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PolicyFragment{}, &PolicyFragmentList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen_test.go index 5a08fc46450..cd0ef387d23 100644 --- a/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/policy_fragment_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPolicyFragment(gens map[string]gopter.Gen) { gens["Status"] = PolicyFragment_STATUSGenerator() } +func Test_PolicyFragmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyFragmentOperatorSpec to PolicyFragmentOperatorSpec via AssignProperties_To_PolicyFragmentOperatorSpec & AssignProperties_From_PolicyFragmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyFragmentOperatorSpec tests if a specific instance of PolicyFragmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.PolicyFragmentOperatorSpec + err := copied.AssignProperties_To_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyFragmentOperatorSpec + err = actual.AssignProperties_From_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyFragmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyFragmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyFragmentOperatorSpec runs a test to see if a specific instance of PolicyFragmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyFragmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyFragmentOperatorSpec instances for property testing - lazily instantiated by +// PolicyFragmentOperatorSpecGenerator() +var policyFragmentOperatorSpecGenerator gopter.Gen + +// PolicyFragmentOperatorSpecGenerator returns a generator of PolicyFragmentOperatorSpec instances for property testing. +func PolicyFragmentOperatorSpecGenerator() gopter.Gen { + if policyFragmentOperatorSpecGenerator != nil { + return policyFragmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyFragmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragmentOperatorSpec{}), generators) + + return policyFragmentOperatorSpecGenerator +} + func Test_PolicyFragment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForPolicyFragment_Spec(subject PolicyFragment_Spec) var policyFragment_SpecGenerator gopter.Gen // PolicyFragment_SpecGenerator returns a generator of PolicyFragment_Spec instances for property testing. +// We first initialize policyFragment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PolicyFragment_SpecGenerator() gopter.Gen { if policyFragment_SpecGenerator != nil { return policyFragment_SpecGenerator @@ -369,6 +469,12 @@ func PolicyFragment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) + AddRelatedPropertyGeneratorsForPolicyFragment_Spec(generators) + policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + return policyFragment_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopt gens["Format"] = gen.PtrOf(gen.OneConstOf(PolicyFragmentContractProperties_Format_Rawxml, PolicyFragmentContractProperties_Format_Xml)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicyFragment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyFragmentOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/policy_types_gen.go index 21bf06caa2a..225a39a3eb4 100644 --- a/v2/api/apimanagement/v1api20230501preview/policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (policy *Policy) Default() { // defaultImpl applies the code generated defaults to the Policy resource func (policy *Policy) defaultImpl() {} +var _ configmaps.Exporter = &Policy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *Policy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Policy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *Policy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Policy{} // AzureName returns the Azure name of the resource (always "policy") @@ -206,7 +229,7 @@ func (policy *Policy) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (policy *Policy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -224,9 +247,23 @@ func (policy *Policy) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *Policy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *Policy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -241,6 +278,14 @@ func (policy *Policy) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *Policy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *Policy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Policy) @@ -326,6 +371,10 @@ type Policy_Spec struct { // Format: Format of the policyContent. Format *PolicyContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -389,6 +438,8 @@ func (policy *Policy_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefere } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -470,6 +521,18 @@ func (policy *Policy_Spec) AssignProperties_From_Policy_Spec(source *storage.Pol policy.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -498,6 +561,18 @@ func (policy *Policy_Spec) AssignProperties_To_Policy_Spec(destination *storage. destination.Format = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.PolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_PolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -762,6 +837,110 @@ var policyContractProperties_Format_STATUS_Values = map[string]PolicyContractPro "xml-link": PolicyContractProperties_Format_STATUS_XmlLink, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyOperatorSpec populates our PolicyOperatorSpec from the provided source PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_From_PolicyOperatorSpec(source *storage.PolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PolicyOperatorSpec populates the provided destination PolicyOperatorSpec from our PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_To_PolicyOperatorSpec(destination *storage.PolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Policy{}, &PolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/policy_types_gen_test.go index 1c1b3664612..7346cb3c4bc 100644 --- a/v2/api/apimanagement/v1api20230501preview/policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/policy_types_gen_test.go @@ -165,6 +165,102 @@ func AddRelatedPropertyGeneratorsForPolicy(gens map[string]gopter.Gen) { gens["Status"] = Policy_STATUSGenerator() } +func Test_PolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyOperatorSpec to PolicyOperatorSpec via AssignProperties_To_PolicyOperatorSpec & AssignProperties_From_PolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyOperatorSpec tests if a specific instance of PolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.PolicyOperatorSpec + err := copied.AssignProperties_To_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyOperatorSpec + err = actual.AssignProperties_From_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyOperatorSpec runs a test to see if a specific instance of PolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyOperatorSpec instances for property testing - lazily instantiated by PolicyOperatorSpecGenerator() +var policyOperatorSpecGenerator gopter.Gen + +// PolicyOperatorSpecGenerator returns a generator of PolicyOperatorSpec instances for property testing. +func PolicyOperatorSpecGenerator() gopter.Gen { + if policyOperatorSpecGenerator != nil { + return policyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyOperatorSpec{}), generators) + + return policyOperatorSpecGenerator +} + func Test_Policy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +456,9 @@ func RunJSONSerializationTestForPolicy_Spec(subject Policy_Spec) string { var policy_SpecGenerator gopter.Gen // Policy_SpecGenerator returns a generator of Policy_Spec instances for property testing. +// We first initialize policy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Policy_SpecGenerator() gopter.Gen { if policy_SpecGenerator != nil { return policy_SpecGenerator @@ -369,6 +468,12 @@ func Policy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicy_Spec(generators) policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForPolicy_Spec(generators) + policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + return policy_SpecGenerator } @@ -381,3 +486,8 @@ func AddIndependentPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) PolicyContractProperties_Format_XmlLink)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/product_api_types_gen.go b/v2/api/apimanagement/v1api20230501preview/product_api_types_gen.go index dafbe8c969d..72e122ae7c6 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_api_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/product_api_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (productApi *ProductApi) defaultAzureName() { // defaultImpl applies the code generated defaults to the ProductApi resource func (productApi *ProductApi) defaultImpl() { productApi.defaultAzureName() } +var _ configmaps.Exporter = &ProductApi{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (productApi *ProductApi) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductApi{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (productApi *ProductApi) SecretDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductApi{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (productApi *ProductApi) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (productApi *ProductApi) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){productApi.validateResourceReferences, productApi.validateOwnerReference} + return []func() (admission.Warnings, error){productApi.validateResourceReferences, productApi.validateOwnerReference, productApi.validateSecretDestinations, productApi.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,9 +253,23 @@ func (productApi *ProductApi) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return productApi.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return productApi.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return productApi.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (productApi *ProductApi) validateConfigMapDestinations() (admission.Warnings, error) { + if productApi.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(productApi, nil, productApi.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (productApi *ProductApi) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(productApi) @@ -247,6 +284,14 @@ func (productApi *ProductApi) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (productApi *ProductApi) validateSecretDestinations() (admission.Warnings, error) { + if productApi.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(productApi, nil, productApi.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (productApi *ProductApi) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ProductApi) @@ -336,6 +381,10 @@ type ProductApi_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductApiOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -372,6 +421,8 @@ func (productApi *ProductApi_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": productApi.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": productApi.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -438,6 +489,18 @@ func (productApi *ProductApi_Spec) AssignProperties_From_ProductApi_Spec(source // AzureName productApi.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductApiOperatorSpec + err := operatorSpec.AssignProperties_From_ProductApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductApiOperatorSpec() to populate field OperatorSpec") + } + productApi.OperatorSpec = &operatorSpec + } else { + productApi.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -458,6 +521,18 @@ func (productApi *ProductApi_Spec) AssignProperties_To_ProductApi_Spec(destinati // AzureName destination.AzureName = productApi.AzureName + // OperatorSpec + if productApi.OperatorSpec != nil { + var operatorSpec storage.ProductApiOperatorSpec + err := productApi.OperatorSpec.AssignProperties_To_ProductApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = productApi.OriginalVersion() @@ -592,6 +667,110 @@ func (productApi *ProductApi_STATUS) AssignProperties_To_ProductApi_STATUS(desti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductApiOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductApiOperatorSpec populates our ProductApiOperatorSpec from the provided source ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_From_ProductApiOperatorSpec(source *storage.ProductApiOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductApiOperatorSpec populates the provided destination ProductApiOperatorSpec from our ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_To_ProductApiOperatorSpec(destination *storage.ProductApiOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ProductApi{}, &ProductApiList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/product_api_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/product_api_types_gen_test.go index 29dc347185b..0c4cd79016e 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/product_api_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForProductApi(gens map[string]gopter.Gen) { gens["Status"] = ProductApi_STATUSGenerator() } +func Test_ProductApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductApiOperatorSpec to ProductApiOperatorSpec via AssignProperties_To_ProductApiOperatorSpec & AssignProperties_From_ProductApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductApiOperatorSpec tests if a specific instance of ProductApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ProductApiOperatorSpec + err := copied.AssignProperties_To_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductApiOperatorSpec + err = actual.AssignProperties_From_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductApiOperatorSpec runs a test to see if a specific instance of ProductApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductApiOperatorSpec instances for property testing - lazily instantiated by +// ProductApiOperatorSpecGenerator() +var productApiOperatorSpecGenerator gopter.Gen + +// ProductApiOperatorSpecGenerator returns a generator of ProductApiOperatorSpec instances for property testing. +func ProductApiOperatorSpecGenerator() gopter.Gen { + if productApiOperatorSpecGenerator != nil { + return productApiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productApiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductApiOperatorSpec{}), generators) + + return productApiOperatorSpecGenerator +} + func Test_ProductApi_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -346,6 +443,9 @@ func RunJSONSerializationTestForProductApi_Spec(subject ProductApi_Spec) string var productApi_SpecGenerator gopter.Gen // ProductApi_SpecGenerator returns a generator of ProductApi_Spec instances for property testing. +// We first initialize productApi_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductApi_SpecGenerator() gopter.Gen { if productApi_SpecGenerator != nil { return productApi_SpecGenerator @@ -355,6 +455,12 @@ func ProductApi_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductApi_Spec(generators) productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductApi_Spec(generators) + AddRelatedPropertyGeneratorsForProductApi_Spec(generators) + productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + return productApi_SpecGenerator } @@ -362,3 +468,8 @@ func ProductApi_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { gens["AzureName"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForProductApi_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductApiOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen.go index bb91d63ae7c..3f8188b6a8e 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (policy *ProductPolicy) Default() { // defaultImpl applies the code generated defaults to the ProductPolicy resource func (policy *ProductPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ProductPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ProductPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ProductPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductPolicy{} // AzureName returns the Azure name of the resource (always "policy") @@ -206,7 +229,7 @@ func (policy *ProductPolicy) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (policy *ProductPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -224,9 +247,23 @@ func (policy *ProductPolicy) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ProductPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *ProductPolicy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -241,6 +278,14 @@ func (policy *ProductPolicy) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ProductPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ProductPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ProductPolicy) @@ -326,6 +371,10 @@ type ProductPolicy_Spec struct { // Format: Format of the policyContent. Format *PolicyContractProperties_Format `json:"format,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -389,6 +438,8 @@ func (policy *ProductPolicy_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -470,6 +521,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_From_ProductPolicy_Spec(sourc policy.Format = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ProductPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -498,6 +561,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_To_ProductPolicy_Spec(destina destination.Format = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ProductPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ProductPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -727,6 +802,110 @@ func (policy *ProductPolicy_STATUS) AssignProperties_To_ProductPolicy_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductPolicyOperatorSpec populates our ProductPolicyOperatorSpec from the provided source ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_From_ProductPolicyOperatorSpec(source *storage.ProductPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductPolicyOperatorSpec populates the provided destination ProductPolicyOperatorSpec from our ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_To_ProductPolicyOperatorSpec(destination *storage.ProductPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ProductPolicy{}, &ProductPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen_test.go index 149dec4f4f5..0b65348d710 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/product_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForProductPolicy(gens map[string]gopter.Gen) { gens["Status"] = ProductPolicy_STATUSGenerator() } +func Test_ProductPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductPolicyOperatorSpec to ProductPolicyOperatorSpec via AssignProperties_To_ProductPolicyOperatorSpec & AssignProperties_From_ProductPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductPolicyOperatorSpec tests if a specific instance of ProductPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ProductPolicyOperatorSpec + err := copied.AssignProperties_To_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductPolicyOperatorSpec + err = actual.AssignProperties_From_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductPolicyOperatorSpec runs a test to see if a specific instance of ProductPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductPolicyOperatorSpec instances for property testing - lazily instantiated by +// ProductPolicyOperatorSpecGenerator() +var productPolicyOperatorSpecGenerator gopter.Gen + +// ProductPolicyOperatorSpecGenerator returns a generator of ProductPolicyOperatorSpec instances for property testing. +func ProductPolicyOperatorSpecGenerator() gopter.Gen { + if productPolicyOperatorSpecGenerator != nil { + return productPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicyOperatorSpec{}), generators) + + return productPolicyOperatorSpecGenerator +} + func Test_ProductPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForProductPolicy_Spec(subject ProductPolicy_Spec) s var productPolicy_SpecGenerator gopter.Gen // ProductPolicy_SpecGenerator returns a generator of ProductPolicy_Spec instances for property testing. +// We first initialize productPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductPolicy_SpecGenerator() gopter.Gen { if productPolicy_SpecGenerator != nil { return productPolicy_SpecGenerator @@ -370,6 +470,12 @@ func ProductPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForProductPolicy_Spec(generators) + productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + return productPolicy_SpecGenerator } @@ -382,3 +488,8 @@ func AddIndependentPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopte PolicyContractProperties_Format_XmlLink)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProductPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/product_types_gen.go b/v2/api/apimanagement/v1api20230501preview/product_types_gen.go index 0cba07010d1..45bb18272e8 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/product_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (product *Product) defaultAzureName() { // defaultImpl applies the code generated defaults to the Product resource func (product *Product) defaultImpl() { product.defaultAzureName() } +var _ configmaps.Exporter = &Product{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (product *Product) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Product{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (product *Product) SecretDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Product{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (product *Product) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (product *Product) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){product.validateResourceReferences, product.validateOwnerReference} + return []func() (admission.Warnings, error){product.validateResourceReferences, product.validateOwnerReference, product.validateSecretDestinations, product.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,9 +254,23 @@ func (product *Product) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return product.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return product.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return product.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (product *Product) validateConfigMapDestinations() (admission.Warnings, error) { + if product.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(product, nil, product.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (product *Product) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(product) @@ -248,6 +285,14 @@ func (product *Product) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (product *Product) validateSecretDestinations() (admission.Warnings, error) { + if product.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(product, nil, product.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (product *Product) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Product) @@ -353,6 +398,10 @@ type Product_Spec struct { // DisplayName: Product name. DisplayName *string `json:"displayName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProductOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -477,6 +526,8 @@ func (product *Product_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": product.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -605,6 +656,18 @@ func (product *Product_Spec) AssignProperties_From_Product_Spec(source *storage. product.DisplayName = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductOperatorSpec + err := operatorSpec.AssignProperties_From_ProductOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductOperatorSpec() to populate field OperatorSpec") + } + product.OperatorSpec = &operatorSpec + } else { + product.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -672,6 +735,18 @@ func (product *Product_Spec) AssignProperties_To_Product_Spec(destination *stora destination.DisplayName = nil } + // OperatorSpec + if product.OperatorSpec != nil { + var operatorSpec storage.ProductOperatorSpec + err := product.OperatorSpec.AssignProperties_To_ProductOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = product.OriginalVersion() @@ -1071,6 +1146,110 @@ var productContractProperties_State_STATUS_Values = map[string]ProductContractPr "published": ProductContractProperties_State_STATUS_Published, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductOperatorSpec populates our ProductOperatorSpec from the provided source ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_From_ProductOperatorSpec(source *storage.ProductOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProductOperatorSpec populates the provided destination ProductOperatorSpec from our ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_To_ProductOperatorSpec(destination *storage.ProductOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Product{}, &ProductList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/product_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/product_types_gen_test.go index e8332cb9c9a..d7c3c0ff6a4 100644 --- a/v2/api/apimanagement/v1api20230501preview/product_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/product_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForProduct(gens map[string]gopter.Gen) { gens["Status"] = Product_STATUSGenerator() } +func Test_ProductOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductOperatorSpec to ProductOperatorSpec via AssignProperties_To_ProductOperatorSpec & AssignProperties_From_ProductOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductOperatorSpec tests if a specific instance of ProductOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ProductOperatorSpec + err := copied.AssignProperties_To_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductOperatorSpec + err = actual.AssignProperties_From_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductOperatorSpec runs a test to see if a specific instance of ProductOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductOperatorSpec instances for property testing - lazily instantiated by +// ProductOperatorSpecGenerator() +var productOperatorSpecGenerator gopter.Gen + +// ProductOperatorSpecGenerator returns a generator of ProductOperatorSpec instances for property testing. +func ProductOperatorSpecGenerator() gopter.Gen { + if productOperatorSpecGenerator != nil { + return productOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductOperatorSpec{}), generators) + + return productOperatorSpecGenerator +} + func Test_Product_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForProduct_Spec(subject Product_Spec) string { var product_SpecGenerator gopter.Gen // Product_SpecGenerator returns a generator of Product_Spec instances for property testing. +// We first initialize product_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Product_SpecGenerator() gopter.Gen { if product_SpecGenerator != nil { return product_SpecGenerator @@ -370,6 +470,12 @@ func Product_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProduct_Spec(generators) product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProduct_Spec(generators) + AddRelatedPropertyGeneratorsForProduct_Spec(generators) + product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + return product_SpecGenerator } @@ -384,3 +490,8 @@ func AddIndependentPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) gens["SubscriptionsLimit"] = gen.PtrOf(gen.Int()) gens["Terms"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProduct_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/service_types_gen.go b/v2/api/apimanagement/v1api20230501preview/service_types_gen.go index cd894796f06..741b96f5edf 100644 --- a/v2/api/apimanagement/v1api20230501preview/service_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/service_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +108,26 @@ func (service *Service) defaultAzureName() { // defaultImpl applies the code generated defaults to the Service resource func (service *Service) defaultImpl() { service.defaultAzureName() } +var _ configmaps.Exporter = &Service{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *Service) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Service{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *Service) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Service{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (service *Service) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (service *Service) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations, service.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -231,12 +253,26 @@ func (service *Service) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return service.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *Service) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (service *Service) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&service.Spec) @@ -260,6 +296,14 @@ func (service *Service) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *Service) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *Service) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Service) @@ -417,6 +461,10 @@ type Service_Spec struct { // NotificationSenderEmail: Email address from which the notification will be sent. NotificationSenderEmail *string `json:"notificationSenderEmail,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -825,6 +873,8 @@ func (service *Service_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1127,6 +1177,18 @@ func (service *Service_Spec) AssignProperties_From_Service_Spec(source *storage. service.NotificationSenderEmail = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServiceOperatorSpec + err := operatorSpec.AssignProperties_From_ServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1371,6 +1433,18 @@ func (service *Service_Spec) AssignProperties_To_Service_Spec(destination *stora destination.NotificationSenderEmail = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.ServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_ServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -5534,6 +5608,110 @@ func (wrapper *RemotePrivateEndpointConnectionWrapper_STATUS) AssignProperties_T return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServiceOperatorSpec populates our ServiceOperatorSpec from the provided source ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_From_ServiceOperatorSpec(source *storage.ServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServiceOperatorSpec populates the provided destination ServiceOperatorSpec from our ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_To_ServiceOperatorSpec(destination *storage.ServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/apimanagement/v1api20230501preview/service_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/service_types_gen_test.go index 72a49111db2..ab50476fc04 100644 --- a/v2/api/apimanagement/v1api20230501preview/service_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/service_types_gen_test.go @@ -2344,6 +2344,103 @@ func AddRelatedPropertyGeneratorsForService(gens map[string]gopter.Gen) { gens["Status"] = Service_STATUSGenerator() } +func Test_ServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServiceOperatorSpec to ServiceOperatorSpec via AssignProperties_To_ServiceOperatorSpec & AssignProperties_From_ServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServiceOperatorSpec tests if a specific instance of ServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230501ps.ServiceOperatorSpec + err := copied.AssignProperties_To_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServiceOperatorSpec + err = actual.AssignProperties_From_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServiceOperatorSpec runs a test to see if a specific instance of ServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServiceOperatorSpec instances for property testing - lazily instantiated by +// ServiceOperatorSpecGenerator() +var serviceOperatorSpecGenerator gopter.Gen + +// ServiceOperatorSpecGenerator returns a generator of ServiceOperatorSpec instances for property testing. +func ServiceOperatorSpecGenerator() gopter.Gen { + if serviceOperatorSpecGenerator != nil { + return serviceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serviceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServiceOperatorSpec{}), generators) + + return serviceOperatorSpecGenerator +} + func Test_Service_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2648,6 +2745,7 @@ func AddRelatedPropertyGeneratorsForService_Spec(gens map[string]gopter.Gen) { gens["ConfigurationApi"] = gen.PtrOf(ConfigurationApiGenerator()) gens["HostnameConfigurations"] = gen.SliceOf(HostnameConfigurationGenerator()) gens["Identity"] = gen.PtrOf(ApiManagementServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServiceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(ApiManagementServiceSkuPropertiesGenerator()) gens["VirtualNetworkConfiguration"] = gen.PtrOf(VirtualNetworkConfigurationGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen.go index c05d08fcf01..2b6ff368f35 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -63,6 +66,26 @@ func (api *Api) ConvertTo(hub conversion.Hub) error { return api.AssignProperties_To_Api(destination) } +var _ configmaps.Exporter = &Api{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (api *Api) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Api{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (api *Api) SecretDestinationExpressions() []*core.DestinationExpression { + if api.Spec.OperatorSpec == nil { + return nil + } + return api.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Api{} // AzureName returns the Azure name of the resource @@ -247,6 +270,7 @@ type Api_Spec struct { Format *string `json:"format,omitempty"` IsCurrent *bool `json:"isCurrent,omitempty"` License *ApiLicenseInformation `json:"license,omitempty"` + OperatorSpec *ApiOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -416,6 +440,18 @@ func (api *Api_Spec) AssignProperties_From_Api_Spec(source *storage.Api_Spec) er api.License = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiOperatorSpec + err := operatorSpec.AssignProperties_From_ApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiOperatorSpec() to populate field OperatorSpec") + } + api.OperatorSpec = &operatorSpec + } else { + api.OperatorSpec = nil + } + // OriginalVersion api.OriginalVersion = source.OriginalVersion @@ -604,6 +640,18 @@ func (api *Api_Spec) AssignProperties_To_Api_Spec(destination *storage.Api_Spec) destination.License = nil } + // OperatorSpec + if api.OperatorSpec != nil { + var operatorSpec storage.ApiOperatorSpec + err := api.OperatorSpec.AssignProperties_To_ApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = api.OriginalVersion @@ -1491,6 +1539,136 @@ func (information *ApiLicenseInformation_STATUS) AssignProperties_To_ApiLicenseI return nil } +// Storage version of v1api20230501preview.ApiOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiOperatorSpec populates our ApiOperatorSpec from the provided source ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_From_ApiOperatorSpec(source *storage.ApiOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForApiOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForApiOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ApiOperatorSpec populates the provided destination ApiOperatorSpec from our ApiOperatorSpec +func (operator *ApiOperatorSpec) AssignProperties_To_ApiOperatorSpec(destination *storage.ApiOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForApiOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForApiOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230501preview.ApiVersionSetContractDetails // An API Version Set contains the common configuration for a set of API Versions relating type ApiVersionSetContractDetails struct { @@ -2234,6 +2412,11 @@ type augmentConversionForApiLicenseInformation_STATUS interface { AssignPropertiesTo(dst *storage.ApiLicenseInformation_STATUS) error } +type augmentConversionForApiOperatorSpec interface { + AssignPropertiesFrom(src *storage.ApiOperatorSpec) error + AssignPropertiesTo(dst *storage.ApiOperatorSpec) error +} + type augmentConversionForApiVersionSetContractDetails interface { AssignPropertiesFrom(src *storage.ApiVersionSetContractDetails) error AssignPropertiesTo(dst *storage.ApiVersionSetContractDetails) error diff --git a/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen_test.go index 52e755e3fc3..547c9422a45 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/api_types_gen_test.go @@ -686,6 +686,102 @@ func AddIndependentPropertyGeneratorsForApiLicenseInformation_STATUS(gens map[st gens["Url"] = gen.PtrOf(gen.AlphaString()) } +func Test_ApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiOperatorSpec to ApiOperatorSpec via AssignProperties_To_ApiOperatorSpec & AssignProperties_From_ApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiOperatorSpec tests if a specific instance of ApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApiOperatorSpec + err := copied.AssignProperties_To_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiOperatorSpec + err = actual.AssignProperties_From_ApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiOperatorSpec, ApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiOperatorSpec runs a test to see if a specific instance of ApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiOperatorSpec(subject ApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiOperatorSpec instances for property testing - lazily instantiated by ApiOperatorSpecGenerator() +var apiOperatorSpecGenerator gopter.Gen + +// ApiOperatorSpecGenerator returns a generator of ApiOperatorSpec instances for property testing. +func ApiOperatorSpecGenerator() gopter.Gen { + if apiOperatorSpecGenerator != nil { + return apiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiOperatorSpec{}), generators) + + return apiOperatorSpecGenerator +} + func Test_ApiVersionSetContractDetails_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1175,6 +1271,7 @@ func AddRelatedPropertyGeneratorsForApi_Spec(gens map[string]gopter.Gen) { gens["AuthenticationSettings"] = gen.PtrOf(AuthenticationSettingsContractGenerator()) gens["Contact"] = gen.PtrOf(ApiContactInformationGenerator()) gens["License"] = gen.PtrOf(ApiLicenseInformationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApiOperatorSpecGenerator()) gens["SubscriptionKeyParameterNames"] = gen.PtrOf(SubscriptionKeyParameterNamesContractGenerator()) gens["WsdlSelector"] = gen.PtrOf(ApiCreateOrUpdateProperties_WsdlSelectorGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen.go index a9d79c1dd63..666478e0da7 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (versionSet *ApiVersionSet) ConvertTo(hub conversion.Hub) error { return versionSet.AssignProperties_To_ApiVersionSet(destination) } +var _ configmaps.Exporter = &ApiVersionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (versionSet *ApiVersionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApiVersionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (versionSet *ApiVersionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if versionSet.Spec.OperatorSpec == nil { + return nil + } + return versionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ApiVersionSet{} // AzureName returns the Azure name of the resource @@ -231,10 +254,11 @@ type ApiVersionSetList struct { type ApiVersionSet_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + OperatorSpec *ApiVersionSetOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_From_ApiVersionSet_Spec(s // DisplayName versionSet.DisplayName = genruntime.ClonePointerToString(source.DisplayName) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApiVersionSetOperatorSpec + err := operatorSpec.AssignProperties_From_ApiVersionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + versionSet.OperatorSpec = &operatorSpec + } else { + versionSet.OperatorSpec = nil + } + // OriginalVersion versionSet.OriginalVersion = source.OriginalVersion @@ -365,6 +401,18 @@ func (versionSet *ApiVersionSet_Spec) AssignProperties_To_ApiVersionSet_Spec(des // DisplayName destination.DisplayName = genruntime.ClonePointerToString(versionSet.DisplayName) + // OperatorSpec + if versionSet.OperatorSpec != nil { + var operatorSpec storage.ApiVersionSetOperatorSpec + err := versionSet.OperatorSpec.AssignProperties_To_ApiVersionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApiVersionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = versionSet.OriginalVersion @@ -578,6 +626,136 @@ type augmentConversionForApiVersionSet interface { AssignPropertiesTo(dst *storage.ApiVersionSet) error } +// Storage version of v1api20230501preview.ApiVersionSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApiVersionSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApiVersionSetOperatorSpec populates our ApiVersionSetOperatorSpec from the provided source ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_From_ApiVersionSetOperatorSpec(source *storage.ApiVersionSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForApiVersionSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForApiVersionSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ApiVersionSetOperatorSpec populates the provided destination ApiVersionSetOperatorSpec from our ApiVersionSetOperatorSpec +func (operator *ApiVersionSetOperatorSpec) AssignProperties_To_ApiVersionSetOperatorSpec(destination *storage.ApiVersionSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForApiVersionSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForApiVersionSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForApiVersionSet_Spec interface { AssignPropertiesFrom(src *storage.ApiVersionSet_Spec) error AssignPropertiesTo(dst *storage.ApiVersionSet_Spec) error @@ -588,6 +766,11 @@ type augmentConversionForApiVersionSet_STATUS interface { AssignPropertiesTo(dst *storage.ApiVersionSet_STATUS) error } +type augmentConversionForApiVersionSetOperatorSpec interface { + AssignPropertiesFrom(src *storage.ApiVersionSetOperatorSpec) error + AssignPropertiesTo(dst *storage.ApiVersionSetOperatorSpec) error +} + func init() { SchemeBuilder.Register(&ApiVersionSet{}, &ApiVersionSetList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen_test.go index 2eecb8e303c..9ff24f8d93a 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/api_version_set_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForApiVersionSet(gens map[string]gopter.Gen) { gens["Status"] = ApiVersionSet_STATUSGenerator() } +func Test_ApiVersionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApiVersionSetOperatorSpec to ApiVersionSetOperatorSpec via AssignProperties_To_ApiVersionSetOperatorSpec & AssignProperties_From_ApiVersionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApiVersionSetOperatorSpec tests if a specific instance of ApiVersionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApiVersionSetOperatorSpec + err := copied.AssignProperties_To_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApiVersionSetOperatorSpec + err = actual.AssignProperties_From_ApiVersionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApiVersionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApiVersionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApiVersionSetOperatorSpec, ApiVersionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApiVersionSetOperatorSpec runs a test to see if a specific instance of ApiVersionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApiVersionSetOperatorSpec(subject ApiVersionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApiVersionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApiVersionSetOperatorSpec instances for property testing - lazily instantiated by +// ApiVersionSetOperatorSpecGenerator() +var apiVersionSetOperatorSpecGenerator gopter.Gen + +// ApiVersionSetOperatorSpecGenerator returns a generator of ApiVersionSetOperatorSpec instances for property testing. +func ApiVersionSetOperatorSpecGenerator() gopter.Gen { + if apiVersionSetOperatorSpecGenerator != nil { + return apiVersionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + apiVersionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSetOperatorSpec{}), generators) + + return apiVersionSetOperatorSpecGenerator +} + func Test_ApiVersionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForApiVersionSet_Spec(subject ApiVersionSet_Spec) s var apiVersionSet_SpecGenerator gopter.Gen // ApiVersionSet_SpecGenerator returns a generator of ApiVersionSet_Spec instances for property testing. +// We first initialize apiVersionSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApiVersionSet_SpecGenerator() gopter.Gen { if apiVersionSet_SpecGenerator != nil { return apiVersionSet_SpecGenerator @@ -368,6 +468,12 @@ func ApiVersionSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApiVersionSet_Spec(generators) + AddRelatedPropertyGeneratorsForApiVersionSet_Spec(generators) + apiVersionSet_SpecGenerator = gen.Struct(reflect.TypeOf(ApiVersionSet_Spec{}), generators) + return apiVersionSet_SpecGenerator } @@ -381,3 +487,8 @@ func AddIndependentPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopte gens["VersionQueryName"] = gen.PtrOf(gen.AlphaString()) gens["VersioningScheme"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForApiVersionSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApiVersionSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApiVersionSetOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen.go index d9d4ee5634a..e9cd68a2077 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (provider *AuthorizationProvider) ConvertTo(hub conversion.Hub) error { return provider.AssignProperties_To_AuthorizationProvider(destination) } +var _ configmaps.Exporter = &AuthorizationProvider{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (provider *AuthorizationProvider) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvider{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (provider *AuthorizationProvider) SecretDestinationExpressions() []*core.DestinationExpression { + if provider.Spec.OperatorSpec == nil { + return nil + } + return provider.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvider{} // AzureName returns the Azure name of the resource @@ -239,6 +262,7 @@ type AuthorizationProvider_Spec struct { DisplayName *string `json:"displayName,omitempty"` IdentityProvider *string `json:"identityProvider,omitempty"` Oauth2 *AuthorizationProviderOAuth2Settings `json:"oauth2,omitempty"` + OperatorSpec *AuthorizationProviderOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -325,6 +349,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_From_AuthorizationP provider.Oauth2 = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProviderOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProviderOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + provider.OperatorSpec = &operatorSpec + } else { + provider.OperatorSpec = nil + } + // OriginalVersion provider.OriginalVersion = source.OriginalVersion @@ -382,6 +418,18 @@ func (provider *AuthorizationProvider_Spec) AssignProperties_To_AuthorizationPro destination.Oauth2 = nil } + // OperatorSpec + if provider.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProviderOperatorSpec + err := provider.OperatorSpec.AssignProperties_To_AuthorizationProviderOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProviderOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = provider.OriginalVersion @@ -771,6 +819,136 @@ func (settings *AuthorizationProviderOAuth2Settings_STATUS) AssignProperties_To_ return nil } +// Storage version of v1api20230501preview.AuthorizationProviderOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProviderOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProviderOperatorSpec populates our AuthorizationProviderOperatorSpec from the provided source AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_From_AuthorizationProviderOperatorSpec(source *storage.AuthorizationProviderOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProviderOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProviderOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProviderOperatorSpec populates the provided destination AuthorizationProviderOperatorSpec from our AuthorizationProviderOperatorSpec +func (operator *AuthorizationProviderOperatorSpec) AssignProperties_To_AuthorizationProviderOperatorSpec(destination *storage.AuthorizationProviderOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProviderOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProviderOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForAuthorizationProviderOAuth2Settings interface { AssignPropertiesFrom(src *storage.AuthorizationProviderOAuth2Settings) error AssignPropertiesTo(dst *storage.AuthorizationProviderOAuth2Settings) error @@ -781,6 +959,11 @@ type augmentConversionForAuthorizationProviderOAuth2Settings_STATUS interface { AssignPropertiesTo(dst *storage.AuthorizationProviderOAuth2Settings_STATUS) error } +type augmentConversionForAuthorizationProviderOperatorSpec interface { + AssignPropertiesFrom(src *storage.AuthorizationProviderOperatorSpec) error + AssignPropertiesTo(dst *storage.AuthorizationProviderOperatorSpec) error +} + // Storage version of v1api20230501preview.AuthorizationProviderOAuth2GrantTypes // Authorization Provider oauth2 grant types settings type AuthorizationProviderOAuth2GrantTypes struct { diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen_test.go index 33ecbc44158..fb2cc12011a 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_provider_types_gen_test.go @@ -604,6 +604,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProviderOAuth2Settings_STATUS(g gens["GrantTypes"] = gen.PtrOf(AuthorizationProviderOAuth2GrantTypes_STATUSGenerator()) } +func Test_AuthorizationProviderOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProviderOperatorSpec to AuthorizationProviderOperatorSpec via AssignProperties_To_AuthorizationProviderOperatorSpec & AssignProperties_From_AuthorizationProviderOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec tests if a specific instance of AuthorizationProviderOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProviderOperatorSpec + err := copied.AssignProperties_To_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProviderOperatorSpec + err = actual.AssignProperties_From_AuthorizationProviderOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProviderOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProviderOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProviderOperatorSpec, AuthorizationProviderOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProviderOperatorSpec runs a test to see if a specific instance of AuthorizationProviderOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProviderOperatorSpec(subject AuthorizationProviderOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProviderOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProviderOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProviderOperatorSpecGenerator() +var authorizationProviderOperatorSpecGenerator gopter.Gen + +// AuthorizationProviderOperatorSpecGenerator returns a generator of AuthorizationProviderOperatorSpec instances for property testing. +func AuthorizationProviderOperatorSpecGenerator() gopter.Gen { + if authorizationProviderOperatorSpecGenerator != nil { + return authorizationProviderOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProviderOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProviderOperatorSpec{}), generators) + + return authorizationProviderOperatorSpecGenerator +} + func Test_AuthorizationProvider_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -843,4 +940,5 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvider_Spec(gens map[stri // AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAuthorizationProvider_Spec(gens map[string]gopter.Gen) { gens["Oauth2"] = gen.PtrOf(AuthorizationProviderOAuth2SettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProviderOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen.go index 277c523df7d..1e838a160dc 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (authorization *AuthorizationProvidersAuthorization) ConvertTo(hub conversi return authorization.AssignProperties_To_AuthorizationProvidersAuthorization(destination) } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorization{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authorization *AuthorizationProvidersAuthorization) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorization{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authorization *AuthorizationProvidersAuthorization) SecretDestinationExpressions() []*core.DestinationExpression { + if authorization.Spec.OperatorSpec == nil { + return nil + } + return authorization.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorization{} // AzureName returns the Azure name of the resource @@ -237,9 +260,10 @@ type AuthorizationProvidersAuthorization_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Oauth2GrantType *string `json:"oauth2grantType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Oauth2GrantType *string `json:"oauth2grantType,omitempty"` + OperatorSpec *AuthorizationProvidersAuthorizationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -314,6 +338,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ // Oauth2GrantType authorization.Oauth2GrantType = genruntime.ClonePointerToString(source.Oauth2GrantType) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + authorization.OperatorSpec = &operatorSpec + } else { + authorization.OperatorSpec = nil + } + // OriginalVersion authorization.OriginalVersion = source.OriginalVersion @@ -367,6 +403,18 @@ func (authorization *AuthorizationProvidersAuthorization_Spec) AssignProperties_ // Oauth2GrantType destination.Oauth2GrantType = genruntime.ClonePointerToString(authorization.Oauth2GrantType) + // OperatorSpec + if authorization.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationOperatorSpec + err := authorization.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = authorization.OriginalVersion @@ -672,11 +720,146 @@ func (error *AuthorizationError_STATUS) AssignProperties_To_AuthorizationError_S return nil } +// Storage version of v1api20230501preview.AuthorizationProvidersAuthorizationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec populates our AuthorizationProvidersAuthorizationOperatorSpec from the provided source AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(source *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationOperatorSpec from our AuthorizationProvidersAuthorizationOperatorSpec +func (operator *AuthorizationProvidersAuthorizationOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForAuthorizationError_STATUS interface { AssignPropertiesFrom(src *storage.AuthorizationError_STATUS) error AssignPropertiesTo(dst *storage.AuthorizationError_STATUS) error } +type augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec interface { + AssignPropertiesFrom(src *storage.AuthorizationProvidersAuthorizationOperatorSpec) error + AssignPropertiesTo(dst *storage.AuthorizationProvidersAuthorizationOperatorSpec) error +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorization{}, &AuthorizationProvidersAuthorizationList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen_test.go index 1078e4f3d42..5f9dbdd95c8 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorization_types_gen_test.go @@ -269,6 +269,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization(gens map gens["Status"] = AuthorizationProvidersAuthorization_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationOperatorSpec to AuthorizationProvidersAuthorizationOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProvidersAuthorizationOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec, AuthorizationProvidersAuthorizationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationOperatorSpec(subject AuthorizationProvidersAuthorizationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing - lazily instantiated by +// AuthorizationProvidersAuthorizationOperatorSpecGenerator() +var authorizationProvidersAuthorizationOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorization_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -480,6 +577,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorization_Spec(subject var authorizationProvidersAuthorization_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorization_SpecGenerator returns a generator of AuthorizationProvidersAuthorization_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorization_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorization_SpecGenerator != nil { return authorizationProvidersAuthorization_SpecGenerator @@ -489,6 +589,12 @@ func AuthorizationProvidersAuthorization_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(generators) + authorizationProvidersAuthorization_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorization_Spec{}), generators) + return authorizationProvidersAuthorization_SpecGenerator } @@ -499,3 +605,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec gens["Oauth2GrantType"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorization_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen.go index 2ffcb5411c7..c01aff3005c 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ConvertTo(hub co return policy.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicy(destination) } +var _ configmaps.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AuthorizationProvidersAuthorizationsAccessPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *AuthorizationProvidersAuthorizationsAccessPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AuthorizationProvidersAuthorizationsAccessPolicy{} // AzureName returns the Azure name of the resource @@ -237,10 +260,11 @@ type AuthorizationProvidersAuthorizationsAccessPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ObjectId *string `json:"objectId,omitempty" optionalConfigMapPair:"ObjectId"` - ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ObjectId *string `json:"objectId,omitempty" optionalConfigMapPair:"ObjectId"` + ObjectIdFromConfig *genruntime.ConfigMapReference `json:"objectIdFromConfig,omitempty" optionalConfigMapPair:"ObjectId"` + OperatorSpec *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -334,6 +358,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope policy.ObjectIdFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -402,6 +438,18 @@ func (policy *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) AssignPrope destination.ObjectIdFromConfig = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -622,6 +670,141 @@ type augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicy_STATUS AssignPropertiesTo(dst *storage.AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) error } +// Storage version of v1api20230501preview.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from the provided source AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(source *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec populates the provided destination AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec from our AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec +func (operator *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(destination *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) error +} + func init() { SchemeBuilder.Register(&AuthorizationProvidersAuthorizationsAccessPolicy{}, &AuthorizationProvidersAuthorizationsAccessPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen_test.go index 4569a5891bf..5540b0541c4 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/authorization_providers_authorizations_access_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPo gens["Status"] = AuthorizationProvidersAuthorizationsAccessPolicy_STATUSGenerator() } +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec to AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec & AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec tests if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err := copied.AssignProperties_To_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = actual.AssignProperties_From_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec, AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec runs a test to see if a specific instance of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec(subject AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing - lazily +// instantiated by AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() +var authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator gopter.Gen + +// AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec instances for property testing. +func AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator() gopter.Gen { + if authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator != nil { + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec{}), generators) + + return authorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator +} + func Test_AuthorizationProvidersAuthorizationsAccessPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForAuthorizationProvidersAuthorizationsAccessPolicy var authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator gopter.Gen // AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator returns a generator of AuthorizationProvidersAuthorizationsAccessPolicy_Spec instances for property testing. +// We first initialize authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen { if authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator != nil { return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator @@ -368,6 +468,12 @@ func AuthorizationProvidersAuthorizationsAccessPolicy_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(generators) + authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(AuthorizationProvidersAuthorizationsAccessPolicy_Spec{}), generators) + return authorizationProvidersAuthorizationsAccessPolicy_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForAuthorizationProvidersAuthorizationsAcce gens["OriginalVersion"] = gen.AlphaString() gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAuthorizationProvidersAuthorizationsAccessPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen.go index d464bfa24f6..b587598552b 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (backend *Backend) ConvertTo(hub conversion.Hub) error { return backend.AssignProperties_To_Backend(destination) } +var _ configmaps.Exporter = &Backend{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (backend *Backend) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Backend{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (backend *Backend) SecretDestinationExpressions() []*core.DestinationExpression { + if backend.Spec.OperatorSpec == nil { + return nil + } + return backend.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Backend{} // AzureName returns the Azure name of the resource @@ -240,6 +263,7 @@ type Backend_Spec struct { CircuitBreaker *BackendCircuitBreaker `json:"circuitBreaker,omitempty"` Credentials *BackendCredentialsContract `json:"credentials,omitempty"` Description *string `json:"description,omitempty"` + OperatorSpec *BackendOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -348,6 +372,18 @@ func (backend *Backend_Spec) AssignProperties_From_Backend_Spec(source *storage. // Description backend.Description = genruntime.ClonePointerToString(source.Description) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackendOperatorSpec + err := operatorSpec.AssignProperties_From_BackendOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackendOperatorSpec() to populate field OperatorSpec") + } + backend.OperatorSpec = &operatorSpec + } else { + backend.OperatorSpec = nil + } + // OriginalVersion backend.OriginalVersion = source.OriginalVersion @@ -488,6 +524,18 @@ func (backend *Backend_Spec) AssignProperties_To_Backend_Spec(destination *stora // Description destination.Description = genruntime.ClonePointerToString(backend.Description) + // OperatorSpec + if backend.OperatorSpec != nil { + var operatorSpec storage.BackendOperatorSpec + err := backend.OperatorSpec.AssignProperties_To_BackendOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackendOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = backend.OriginalVersion @@ -1239,6 +1287,136 @@ func (contract *BackendCredentialsContract_STATUS) AssignProperties_To_BackendCr return nil } +// Storage version of v1api20230501preview.BackendOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackendOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackendOperatorSpec populates our BackendOperatorSpec from the provided source BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_From_BackendOperatorSpec(source *storage.BackendOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForBackendOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForBackendOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_BackendOperatorSpec populates the provided destination BackendOperatorSpec from our BackendOperatorSpec +func (operator *BackendOperatorSpec) AssignProperties_To_BackendOperatorSpec(destination *storage.BackendOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForBackendOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForBackendOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230501preview.BackendPool // Backend pool information type BackendPool struct { @@ -1762,6 +1940,11 @@ type augmentConversionForBackendCredentialsContract_STATUS interface { AssignPropertiesTo(dst *storage.BackendCredentialsContract_STATUS) error } +type augmentConversionForBackendOperatorSpec interface { + AssignPropertiesFrom(src *storage.BackendOperatorSpec) error + AssignPropertiesTo(dst *storage.BackendOperatorSpec) error +} + type augmentConversionForBackendProperties interface { AssignPropertiesFrom(src *storage.BackendProperties) error AssignPropertiesTo(dst *storage.BackendProperties) error diff --git a/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen_test.go index 9ea73a789cc..e0b756be8a8 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/backend_types_gen_test.go @@ -742,6 +742,103 @@ func AddRelatedPropertyGeneratorsForBackendCredentialsContract_STATUS(gens map[s gens["Authorization"] = gen.PtrOf(BackendAuthorizationHeaderCredentials_STATUSGenerator()) } +func Test_BackendOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackendOperatorSpec to BackendOperatorSpec via AssignProperties_To_BackendOperatorSpec & AssignProperties_From_BackendOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackendOperatorSpec tests if a specific instance of BackendOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BackendOperatorSpec + err := copied.AssignProperties_To_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackendOperatorSpec + err = actual.AssignProperties_From_BackendOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackendOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackendOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackendOperatorSpec, BackendOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackendOperatorSpec runs a test to see if a specific instance of BackendOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackendOperatorSpec(subject BackendOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackendOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackendOperatorSpec instances for property testing - lazily instantiated by +// BackendOperatorSpecGenerator() +var backendOperatorSpecGenerator gopter.Gen + +// BackendOperatorSpecGenerator returns a generator of BackendOperatorSpec instances for property testing. +func BackendOperatorSpecGenerator() gopter.Gen { + if backendOperatorSpecGenerator != nil { + return backendOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backendOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackendOperatorSpec{}), generators) + + return backendOperatorSpecGenerator +} + func Test_BackendPool_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2090,6 +2187,7 @@ func AddIndependentPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForBackend_Spec(gens map[string]gopter.Gen) { gens["CircuitBreaker"] = gen.PtrOf(BackendCircuitBreakerGenerator()) gens["Credentials"] = gen.PtrOf(BackendCredentialsContractGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BackendOperatorSpecGenerator()) gens["Pool"] = gen.PtrOf(BackendPoolGenerator()) gens["Properties"] = gen.PtrOf(BackendPropertiesGenerator()) gens["Proxy"] = gen.PtrOf(BackendProxyContractGenerator()) diff --git a/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen.go index 69a31b0fdcf..d87450abf28 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (value *NamedValue) ConvertTo(hub conversion.Hub) error { return value.AssignProperties_To_NamedValue(destination) } +var _ configmaps.Exporter = &NamedValue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (value *NamedValue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamedValue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (value *NamedValue) SecretDestinationExpressions() []*core.DestinationExpression { + if value.Spec.OperatorSpec == nil { + return nil + } + return value.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamedValue{} // AzureName returns the Azure name of the resource @@ -239,6 +262,7 @@ type NamedValue_Spec struct { AzureName string `json:"azureName,omitempty"` DisplayName *string `json:"displayName,omitempty"` KeyVault *KeyVaultContractCreateProperties `json:"keyVault,omitempty"` + OperatorSpec *NamedValueOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -325,6 +349,18 @@ func (value *NamedValue_Spec) AssignProperties_From_NamedValue_Spec(source *stor value.KeyVault = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamedValueOperatorSpec + err := operatorSpec.AssignProperties_From_NamedValueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamedValueOperatorSpec() to populate field OperatorSpec") + } + value.OperatorSpec = &operatorSpec + } else { + value.OperatorSpec = nil + } + // OriginalVersion value.OriginalVersion = source.OriginalVersion @@ -393,6 +429,18 @@ func (value *NamedValue_Spec) AssignProperties_To_NamedValue_Spec(destination *s destination.KeyVault = nil } + // OperatorSpec + if value.OperatorSpec != nil { + var operatorSpec storage.NamedValueOperatorSpec + err := value.OperatorSpec.AssignProperties_To_NamedValueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamedValueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = value.OriginalVersion @@ -847,6 +895,136 @@ func (properties *KeyVaultContractProperties_STATUS) AssignProperties_To_KeyVaul return nil } +// Storage version of v1api20230501preview.NamedValueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamedValueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamedValueOperatorSpec populates our NamedValueOperatorSpec from the provided source NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_From_NamedValueOperatorSpec(source *storage.NamedValueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamedValueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamedValueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamedValueOperatorSpec populates the provided destination NamedValueOperatorSpec from our NamedValueOperatorSpec +func (operator *NamedValueOperatorSpec) AssignProperties_To_NamedValueOperatorSpec(destination *storage.NamedValueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamedValueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamedValueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForKeyVaultContractCreateProperties interface { AssignPropertiesFrom(src *storage.KeyVaultContractCreateProperties) error AssignPropertiesTo(dst *storage.KeyVaultContractCreateProperties) error @@ -857,6 +1035,11 @@ type augmentConversionForKeyVaultContractProperties_STATUS interface { AssignPropertiesTo(dst *storage.KeyVaultContractProperties_STATUS) error } +type augmentConversionForNamedValueOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamedValueOperatorSpec) error + AssignPropertiesTo(dst *storage.NamedValueOperatorSpec) error +} + // Storage version of v1api20230501preview.KeyVaultLastAccessStatusContractProperties_STATUS // Issue contract Update Properties. type KeyVaultLastAccessStatusContractProperties_STATUS struct { diff --git a/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen_test.go index 0c678a0dd39..081f82c2d3c 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/named_value_types_gen_test.go @@ -491,6 +491,103 @@ func AddRelatedPropertyGeneratorsForNamedValue(gens map[string]gopter.Gen) { gens["Status"] = NamedValue_STATUSGenerator() } +func Test_NamedValueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamedValueOperatorSpec to NamedValueOperatorSpec via AssignProperties_To_NamedValueOperatorSpec & AssignProperties_From_NamedValueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamedValueOperatorSpec tests if a specific instance of NamedValueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamedValueOperatorSpec + err := copied.AssignProperties_To_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamedValueOperatorSpec + err = actual.AssignProperties_From_NamedValueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamedValueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamedValueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamedValueOperatorSpec, NamedValueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamedValueOperatorSpec runs a test to see if a specific instance of NamedValueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamedValueOperatorSpec(subject NamedValueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamedValueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamedValueOperatorSpec instances for property testing - lazily instantiated by +// NamedValueOperatorSpecGenerator() +var namedValueOperatorSpecGenerator gopter.Gen + +// NamedValueOperatorSpecGenerator returns a generator of NamedValueOperatorSpec instances for property testing. +func NamedValueOperatorSpecGenerator() gopter.Gen { + if namedValueOperatorSpecGenerator != nil { + return namedValueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namedValueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamedValueOperatorSpec{}), generators) + + return namedValueOperatorSpecGenerator +} + func Test_NamedValue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -733,4 +830,5 @@ func AddIndependentPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNamedValue_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamedValue_Spec(gens map[string]gopter.Gen) { gens["KeyVault"] = gen.PtrOf(KeyVaultContractCreatePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamedValueOperatorSpecGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen.go index 57da6eea18b..c18b612d2eb 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (fragment *PolicyFragment) ConvertTo(hub conversion.Hub) error { return fragment.AssignProperties_To_PolicyFragment(destination) } +var _ configmaps.Exporter = &PolicyFragment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fragment *PolicyFragment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PolicyFragment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fragment *PolicyFragment) SecretDestinationExpressions() []*core.DestinationExpression { + if fragment.Spec.OperatorSpec == nil { + return nil + } + return fragment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PolicyFragment{} // AzureName returns the Azure name of the resource @@ -236,10 +259,11 @@ type augmentConversionForPolicyFragment interface { type PolicyFragment_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *PolicyFragmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -314,6 +338,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_From_PolicyFragment_Spec(s // Format fragment.Format = genruntime.ClonePointerToString(source.Format) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyFragmentOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyFragmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + fragment.OperatorSpec = &operatorSpec + } else { + fragment.OperatorSpec = nil + } + // OriginalVersion fragment.OriginalVersion = source.OriginalVersion @@ -362,6 +398,18 @@ func (fragment *PolicyFragment_Spec) AssignProperties_To_PolicyFragment_Spec(des // Format destination.Format = genruntime.ClonePointerToString(fragment.Format) + // OperatorSpec + if fragment.OperatorSpec != nil { + var operatorSpec storage.PolicyFragmentOperatorSpec + err := fragment.OperatorSpec.AssignProperties_To_PolicyFragmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyFragmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = fragment.OriginalVersion @@ -581,6 +629,141 @@ type augmentConversionForPolicyFragment_STATUS interface { AssignPropertiesTo(dst *storage.PolicyFragment_STATUS) error } +// Storage version of v1api20230501preview.PolicyFragmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyFragmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyFragmentOperatorSpec populates our PolicyFragmentOperatorSpec from the provided source PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_From_PolicyFragmentOperatorSpec(source *storage.PolicyFragmentOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForPolicyFragmentOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForPolicyFragmentOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_PolicyFragmentOperatorSpec populates the provided destination PolicyFragmentOperatorSpec from our PolicyFragmentOperatorSpec +func (operator *PolicyFragmentOperatorSpec) AssignProperties_To_PolicyFragmentOperatorSpec(destination *storage.PolicyFragmentOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForPolicyFragmentOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForPolicyFragmentOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForPolicyFragmentOperatorSpec interface { + AssignPropertiesFrom(src *storage.PolicyFragmentOperatorSpec) error + AssignPropertiesTo(dst *storage.PolicyFragmentOperatorSpec) error +} + func init() { SchemeBuilder.Register(&PolicyFragment{}, &PolicyFragmentList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen_test.go index cb3545449b3..7354827ec19 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/policy_fragment_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForPolicyFragment(gens map[string]gopter.Gen) { gens["Status"] = PolicyFragment_STATUSGenerator() } +func Test_PolicyFragmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyFragmentOperatorSpec to PolicyFragmentOperatorSpec via AssignProperties_To_PolicyFragmentOperatorSpec & AssignProperties_From_PolicyFragmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyFragmentOperatorSpec tests if a specific instance of PolicyFragmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PolicyFragmentOperatorSpec + err := copied.AssignProperties_To_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyFragmentOperatorSpec + err = actual.AssignProperties_From_PolicyFragmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyFragmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyFragmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyFragmentOperatorSpec, PolicyFragmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyFragmentOperatorSpec runs a test to see if a specific instance of PolicyFragmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyFragmentOperatorSpec(subject PolicyFragmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyFragmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyFragmentOperatorSpec instances for property testing - lazily instantiated by +// PolicyFragmentOperatorSpecGenerator() +var policyFragmentOperatorSpecGenerator gopter.Gen + +// PolicyFragmentOperatorSpecGenerator returns a generator of PolicyFragmentOperatorSpec instances for property testing. +func PolicyFragmentOperatorSpecGenerator() gopter.Gen { + if policyFragmentOperatorSpecGenerator != nil { + return policyFragmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyFragmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragmentOperatorSpec{}), generators) + + return policyFragmentOperatorSpecGenerator +} + func Test_PolicyFragment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForPolicyFragment_Spec(subject PolicyFragment_Spec) var policyFragment_SpecGenerator gopter.Gen // PolicyFragment_SpecGenerator returns a generator of PolicyFragment_Spec instances for property testing. +// We first initialize policyFragment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PolicyFragment_SpecGenerator() gopter.Gen { if policyFragment_SpecGenerator != nil { return policyFragment_SpecGenerator @@ -368,6 +468,12 @@ func PolicyFragment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicyFragment_Spec(generators) + AddRelatedPropertyGeneratorsForPolicyFragment_Spec(generators) + policyFragment_SpecGenerator = gen.Struct(reflect.TypeOf(PolicyFragment_Spec{}), generators) + return policyFragment_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopt gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicyFragment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicyFragment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyFragmentOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen.go index 8c42e6b31aa..0b893b94a85 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (policy *Policy) ConvertTo(hub conversion.Hub) error { return policy.AssignProperties_To_Policy(destination) } +var _ configmaps.Exporter = &Policy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *Policy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Policy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *Policy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Policy{} // AzureName returns the Azure name of the resource (always "policy") @@ -234,8 +257,9 @@ type augmentConversionForPolicy interface { // Storage version of v1api20230501preview.Policy_Spec type Policy_Spec struct { - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *PolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -304,6 +328,18 @@ func (policy *Policy_Spec) AssignProperties_From_Policy_Spec(source *storage.Pol // Format policy.Format = genruntime.ClonePointerToString(source.Format) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PolicyOperatorSpec + err := operatorSpec.AssignProperties_From_PolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -346,6 +382,18 @@ func (policy *Policy_Spec) AssignProperties_To_Policy_Spec(destination *storage. // Format destination.Format = genruntime.ClonePointerToString(policy.Format) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.PolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_PolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -537,6 +585,141 @@ type augmentConversionForPolicy_STATUS interface { AssignPropertiesTo(dst *storage.Policy_STATUS) error } +// Storage version of v1api20230501preview.PolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PolicyOperatorSpec populates our PolicyOperatorSpec from the provided source PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_From_PolicyOperatorSpec(source *storage.PolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_PolicyOperatorSpec populates the provided destination PolicyOperatorSpec from our PolicyOperatorSpec +func (operator *PolicyOperatorSpec) AssignProperties_To_PolicyOperatorSpec(destination *storage.PolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.PolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.PolicyOperatorSpec) error +} + func init() { SchemeBuilder.Register(&Policy{}, &PolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen_test.go index 9bcc68260c2..0b8760ead1c 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/policy_types_gen_test.go @@ -164,6 +164,102 @@ func AddRelatedPropertyGeneratorsForPolicy(gens map[string]gopter.Gen) { gens["Status"] = Policy_STATUSGenerator() } +func Test_PolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PolicyOperatorSpec to PolicyOperatorSpec via AssignProperties_To_PolicyOperatorSpec & AssignProperties_From_PolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPolicyOperatorSpec tests if a specific instance of PolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PolicyOperatorSpec + err := copied.AssignProperties_To_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PolicyOperatorSpec + err = actual.AssignProperties_From_PolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPolicyOperatorSpec, PolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPolicyOperatorSpec runs a test to see if a specific instance of PolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPolicyOperatorSpec(subject PolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PolicyOperatorSpec instances for property testing - lazily instantiated by PolicyOperatorSpecGenerator() +var policyOperatorSpecGenerator gopter.Gen + +// PolicyOperatorSpecGenerator returns a generator of PolicyOperatorSpec instances for property testing. +func PolicyOperatorSpecGenerator() gopter.Gen { + if policyOperatorSpecGenerator != nil { + return policyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + policyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PolicyOperatorSpec{}), generators) + + return policyOperatorSpecGenerator +} + func Test_Policy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -355,6 +451,9 @@ func RunJSONSerializationTestForPolicy_Spec(subject Policy_Spec) string { var policy_SpecGenerator gopter.Gen // Policy_SpecGenerator returns a generator of Policy_Spec instances for property testing. +// We first initialize policy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Policy_SpecGenerator() gopter.Gen { if policy_SpecGenerator != nil { return policy_SpecGenerator @@ -364,6 +463,12 @@ func Policy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPolicy_Spec(generators) policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForPolicy_Spec(generators) + policy_SpecGenerator = gen.Struct(reflect.TypeOf(Policy_Spec{}), generators) + return policy_SpecGenerator } @@ -373,3 +478,8 @@ func AddIndependentPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen.go index 30f39695497..e67441e9b47 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (productApi *ProductApi) ConvertTo(hub conversion.Hub) error { return productApi.AssignProperties_To_ProductApi(destination) } +var _ configmaps.Exporter = &ProductApi{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (productApi *ProductApi) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductApi{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (productApi *ProductApi) SecretDestinationExpressions() []*core.DestinationExpression { + if productApi.Spec.OperatorSpec == nil { + return nil + } + return productApi.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductApi{} // AzureName returns the Azure name of the resource @@ -235,8 +258,9 @@ type augmentConversionForProductApi interface { type ProductApi_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *ProductApiOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -304,6 +328,18 @@ func (productApi *ProductApi_Spec) AssignProperties_From_ProductApi_Spec(source // AzureName productApi.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductApiOperatorSpec + err := operatorSpec.AssignProperties_From_ProductApiOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductApiOperatorSpec() to populate field OperatorSpec") + } + productApi.OperatorSpec = &operatorSpec + } else { + productApi.OperatorSpec = nil + } + // OriginalVersion productApi.OriginalVersion = source.OriginalVersion @@ -343,6 +379,18 @@ func (productApi *ProductApi_Spec) AssignProperties_To_ProductApi_Spec(destinati // AzureName destination.AzureName = productApi.AzureName + // OperatorSpec + if productApi.OperatorSpec != nil { + var operatorSpec storage.ProductApiOperatorSpec + err := productApi.OperatorSpec.AssignProperties_To_ProductApiOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductApiOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = productApi.OriginalVersion @@ -496,6 +544,141 @@ type augmentConversionForProductApi_STATUS interface { AssignPropertiesTo(dst *storage.ProductApi_STATUS) error } +// Storage version of v1api20230501preview.ProductApiOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductApiOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductApiOperatorSpec populates our ProductApiOperatorSpec from the provided source ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_From_ProductApiOperatorSpec(source *storage.ProductApiOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForProductApiOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductApiOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ProductApiOperatorSpec populates the provided destination ProductApiOperatorSpec from our ProductApiOperatorSpec +func (operator *ProductApiOperatorSpec) AssignProperties_To_ProductApiOperatorSpec(destination *storage.ProductApiOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForProductApiOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductApiOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForProductApiOperatorSpec interface { + AssignPropertiesFrom(src *storage.ProductApiOperatorSpec) error + AssignPropertiesTo(dst *storage.ProductApiOperatorSpec) error +} + func init() { SchemeBuilder.Register(&ProductApi{}, &ProductApiList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen_test.go index fd1328f1903..023e01fe440 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_api_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProductApi(gens map[string]gopter.Gen) { gens["Status"] = ProductApi_STATUSGenerator() } +func Test_ProductApiOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductApiOperatorSpec to ProductApiOperatorSpec via AssignProperties_To_ProductApiOperatorSpec & AssignProperties_From_ProductApiOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductApiOperatorSpec tests if a specific instance of ProductApiOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductApiOperatorSpec + err := copied.AssignProperties_To_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductApiOperatorSpec + err = actual.AssignProperties_From_ProductApiOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductApiOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductApiOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductApiOperatorSpec, ProductApiOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductApiOperatorSpec runs a test to see if a specific instance of ProductApiOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductApiOperatorSpec(subject ProductApiOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductApiOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductApiOperatorSpec instances for property testing - lazily instantiated by +// ProductApiOperatorSpecGenerator() +var productApiOperatorSpecGenerator gopter.Gen + +// ProductApiOperatorSpecGenerator returns a generator of ProductApiOperatorSpec instances for property testing. +func ProductApiOperatorSpecGenerator() gopter.Gen { + if productApiOperatorSpecGenerator != nil { + return productApiOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productApiOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductApiOperatorSpec{}), generators) + + return productApiOperatorSpecGenerator +} + func Test_ProductApi_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -345,6 +442,9 @@ func RunJSONSerializationTestForProductApi_Spec(subject ProductApi_Spec) string var productApi_SpecGenerator gopter.Gen // ProductApi_SpecGenerator returns a generator of ProductApi_Spec instances for property testing. +// We first initialize productApi_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductApi_SpecGenerator() gopter.Gen { if productApi_SpecGenerator != nil { return productApi_SpecGenerator @@ -354,6 +454,12 @@ func ProductApi_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductApi_Spec(generators) productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductApi_Spec(generators) + AddRelatedPropertyGeneratorsForProductApi_Spec(generators) + productApi_SpecGenerator = gen.Struct(reflect.TypeOf(ProductApi_Spec{}), generators) + return productApi_SpecGenerator } @@ -362,3 +468,8 @@ func AddIndependentPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.G gens["AzureName"] = gen.AlphaString() gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForProductApi_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductApi_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductApiOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen.go index 2707dd879d0..886a85c867c 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (policy *ProductPolicy) ConvertTo(hub conversion.Hub) error { return policy.AssignProperties_To_ProductPolicy(destination) } +var _ configmaps.Exporter = &ProductPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ProductPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProductPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ProductPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProductPolicy{} // AzureName returns the Azure name of the resource (always "policy") @@ -234,8 +257,9 @@ type augmentConversionForProductPolicy interface { // Storage version of v1api20230501preview.ProductPolicy_Spec type ProductPolicy_Spec struct { - Format *string `json:"format,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Format *string `json:"format,omitempty"` + OperatorSpec *ProductPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -304,6 +328,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_From_ProductPolicy_Spec(sourc // Format policy.Format = genruntime.ClonePointerToString(source.Format) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ProductPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -346,6 +382,18 @@ func (policy *ProductPolicy_Spec) AssignProperties_To_ProductPolicy_Spec(destina // Format destination.Format = genruntime.ClonePointerToString(policy.Format) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ProductPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ProductPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -537,6 +585,141 @@ type augmentConversionForProductPolicy_STATUS interface { AssignPropertiesTo(dst *storage.ProductPolicy_STATUS) error } +// Storage version of v1api20230501preview.ProductPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductPolicyOperatorSpec populates our ProductPolicyOperatorSpec from the provided source ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_From_ProductPolicyOperatorSpec(source *storage.ProductPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForProductPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ProductPolicyOperatorSpec populates the provided destination ProductPolicyOperatorSpec from our ProductPolicyOperatorSpec +func (operator *ProductPolicyOperatorSpec) AssignProperties_To_ProductPolicyOperatorSpec(destination *storage.ProductPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForProductPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForProductPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.ProductPolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.ProductPolicyOperatorSpec) error +} + func init() { SchemeBuilder.Register(&ProductPolicy{}, &ProductPolicyList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen_test.go index fb678010a1f..82977d20859 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_policy_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProductPolicy(gens map[string]gopter.Gen) { gens["Status"] = ProductPolicy_STATUSGenerator() } +func Test_ProductPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductPolicyOperatorSpec to ProductPolicyOperatorSpec via AssignProperties_To_ProductPolicyOperatorSpec & AssignProperties_From_ProductPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductPolicyOperatorSpec tests if a specific instance of ProductPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductPolicyOperatorSpec + err := copied.AssignProperties_To_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductPolicyOperatorSpec + err = actual.AssignProperties_From_ProductPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductPolicyOperatorSpec, ProductPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductPolicyOperatorSpec runs a test to see if a specific instance of ProductPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductPolicyOperatorSpec(subject ProductPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductPolicyOperatorSpec instances for property testing - lazily instantiated by +// ProductPolicyOperatorSpecGenerator() +var productPolicyOperatorSpecGenerator gopter.Gen + +// ProductPolicyOperatorSpecGenerator returns a generator of ProductPolicyOperatorSpec instances for property testing. +func ProductPolicyOperatorSpecGenerator() gopter.Gen { + if productPolicyOperatorSpecGenerator != nil { + return productPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicyOperatorSpec{}), generators) + + return productPolicyOperatorSpecGenerator +} + func Test_ProductPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -356,6 +453,9 @@ func RunJSONSerializationTestForProductPolicy_Spec(subject ProductPolicy_Spec) s var productPolicy_SpecGenerator gopter.Gen // ProductPolicy_SpecGenerator returns a generator of ProductPolicy_Spec instances for property testing. +// We first initialize productPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ProductPolicy_SpecGenerator() gopter.Gen { if productPolicy_SpecGenerator != nil { return productPolicy_SpecGenerator @@ -365,6 +465,12 @@ func ProductPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProductPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForProductPolicy_Spec(generators) + productPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ProductPolicy_Spec{}), generators) + return productPolicy_SpecGenerator } @@ -374,3 +480,8 @@ func AddIndependentPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopte gens["OriginalVersion"] = gen.AlphaString() gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProductPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProductPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen.go index 87de1e19a18..48ceae1467f 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (product *Product) ConvertTo(hub conversion.Hub) error { return product.AssignProperties_To_Product(destination) } +var _ configmaps.Exporter = &Product{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (product *Product) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Product{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (product *Product) SecretDestinationExpressions() []*core.DestinationExpression { + if product.Spec.OperatorSpec == nil { + return nil + } + return product.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Product{} // AzureName returns the Azure name of the resource @@ -238,10 +261,11 @@ type Product_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + OperatorSpec *ProductOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -327,6 +351,18 @@ func (product *Product_Spec) AssignProperties_From_Product_Spec(source *storage. // DisplayName product.DisplayName = genruntime.ClonePointerToString(source.DisplayName) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProductOperatorSpec + err := operatorSpec.AssignProperties_From_ProductOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProductOperatorSpec() to populate field OperatorSpec") + } + product.OperatorSpec = &operatorSpec + } else { + product.OperatorSpec = nil + } + // OriginalVersion product.OriginalVersion = source.OriginalVersion @@ -397,6 +433,18 @@ func (product *Product_Spec) AssignProperties_To_Product_Spec(destination *stora // DisplayName destination.DisplayName = genruntime.ClonePointerToString(product.DisplayName) + // OperatorSpec + if product.OperatorSpec != nil { + var operatorSpec storage.ProductOperatorSpec + err := product.OperatorSpec.AssignProperties_To_ProductOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProductOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = product.OriginalVersion @@ -657,6 +705,141 @@ type augmentConversionForProduct_STATUS interface { AssignPropertiesTo(dst *storage.Product_STATUS) error } +// Storage version of v1api20230501preview.ProductOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProductOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProductOperatorSpec populates our ProductOperatorSpec from the provided source ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_From_ProductOperatorSpec(source *storage.ProductOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForProductOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ProductOperatorSpec populates the provided destination ProductOperatorSpec from our ProductOperatorSpec +func (operator *ProductOperatorSpec) AssignProperties_To_ProductOperatorSpec(destination *storage.ProductOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForProductOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProductOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForProductOperatorSpec interface { + AssignPropertiesFrom(src *storage.ProductOperatorSpec) error + AssignPropertiesTo(dst *storage.ProductOperatorSpec) error +} + func init() { SchemeBuilder.Register(&Product{}, &ProductList{}) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen_test.go index 9bbb98a8e96..6c0c19415a9 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/product_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProduct(gens map[string]gopter.Gen) { gens["Status"] = Product_STATUSGenerator() } +func Test_ProductOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProductOperatorSpec to ProductOperatorSpec via AssignProperties_To_ProductOperatorSpec & AssignProperties_From_ProductOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProductOperatorSpec tests if a specific instance of ProductOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProductOperatorSpec + err := copied.AssignProperties_To_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProductOperatorSpec + err = actual.AssignProperties_From_ProductOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProductOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProductOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProductOperatorSpec, ProductOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProductOperatorSpec runs a test to see if a specific instance of ProductOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProductOperatorSpec(subject ProductOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProductOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProductOperatorSpec instances for property testing - lazily instantiated by +// ProductOperatorSpecGenerator() +var productOperatorSpecGenerator gopter.Gen + +// ProductOperatorSpecGenerator returns a generator of ProductOperatorSpec instances for property testing. +func ProductOperatorSpecGenerator() gopter.Gen { + if productOperatorSpecGenerator != nil { + return productOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + productOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProductOperatorSpec{}), generators) + + return productOperatorSpecGenerator +} + func Test_Product_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForProduct_Spec(subject Product_Spec) string { var product_SpecGenerator gopter.Gen // Product_SpecGenerator returns a generator of Product_Spec instances for property testing. +// We first initialize product_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Product_SpecGenerator() gopter.Gen { if product_SpecGenerator != nil { return product_SpecGenerator @@ -369,6 +469,12 @@ func Product_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForProduct_Spec(generators) product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForProduct_Spec(generators) + AddRelatedPropertyGeneratorsForProduct_Spec(generators) + product_SpecGenerator = gen.Struct(reflect.TypeOf(Product_Spec{}), generators) + return product_SpecGenerator } @@ -384,3 +490,8 @@ func AddIndependentPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) gens["SubscriptionsLimit"] = gen.PtrOf(gen.Int()) gens["Terms"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForProduct_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForProduct_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProductOperatorSpecGenerator()) +} diff --git a/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen.go index 7bd20ec1b52..7df3b16c856 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (service *Service) ConvertTo(hub conversion.Hub) error { return service.AssignProperties_To_Service(destination) } +var _ configmaps.Exporter = &Service{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *Service) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Service{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *Service) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Service{} // AzureName returns the Azure name of the resource @@ -251,6 +274,7 @@ type Service_Spec struct { Location *string `json:"location,omitempty"` NatGatewayState *string `json:"natGatewayState,omitempty"` NotificationSenderEmail *string `json:"notificationSenderEmail,omitempty"` + OperatorSpec *ServiceOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -477,6 +501,18 @@ func (service *Service_Spec) AssignProperties_From_Service_Spec(source *storage. // NotificationSenderEmail service.NotificationSenderEmail = genruntime.ClonePointerToString(source.NotificationSenderEmail) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServiceOperatorSpec + err := operatorSpec.AssignProperties_From_ServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -701,6 +737,18 @@ func (service *Service_Spec) AssignProperties_To_Service_Spec(destination *stora // NotificationSenderEmail destination.NotificationSenderEmail = genruntime.ClonePointerToString(service.NotificationSenderEmail) + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.ServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_ServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -3049,6 +3097,136 @@ func (wrapper *RemotePrivateEndpointConnectionWrapper_STATUS) AssignProperties_T return nil } +// Storage version of v1api20230501preview.ServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServiceOperatorSpec populates our ServiceOperatorSpec from the provided source ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_From_ServiceOperatorSpec(source *storage.ServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ServiceOperatorSpec populates the provided destination ServiceOperatorSpec from our ServiceOperatorSpec +func (operator *ServiceOperatorSpec) AssignProperties_To_ServiceOperatorSpec(destination *storage.ServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230501preview.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { @@ -3427,6 +3605,11 @@ type augmentConversionForRemotePrivateEndpointConnectionWrapper_STATUS interface AssignPropertiesTo(dst *storage.RemotePrivateEndpointConnectionWrapper_STATUS) error } +type augmentConversionForServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.ServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.ServiceOperatorSpec) error +} + type augmentConversionForSystemData_STATUS interface { AssignPropertiesFrom(src *storage.SystemData_STATUS) error AssignPropertiesTo(dst *storage.SystemData_STATUS) error diff --git a/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen_test.go b/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen_test.go index 1ea07637b99..02f812ca456 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen_test.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/service_types_gen_test.go @@ -2210,6 +2210,103 @@ func AddRelatedPropertyGeneratorsForService(gens map[string]gopter.Gen) { gens["Status"] = Service_STATUSGenerator() } +func Test_ServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServiceOperatorSpec to ServiceOperatorSpec via AssignProperties_To_ServiceOperatorSpec & AssignProperties_From_ServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServiceOperatorSpec tests if a specific instance of ServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServiceOperatorSpec + err := copied.AssignProperties_To_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServiceOperatorSpec + err = actual.AssignProperties_From_ServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServiceOperatorSpec, ServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServiceOperatorSpec runs a test to see if a specific instance of ServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServiceOperatorSpec(subject ServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServiceOperatorSpec instances for property testing - lazily instantiated by +// ServiceOperatorSpecGenerator() +var serviceOperatorSpecGenerator gopter.Gen + +// ServiceOperatorSpecGenerator returns a generator of ServiceOperatorSpec instances for property testing. +func ServiceOperatorSpecGenerator() gopter.Gen { + if serviceOperatorSpecGenerator != nil { + return serviceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serviceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServiceOperatorSpec{}), generators) + + return serviceOperatorSpecGenerator +} + func Test_Service_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2510,6 +2607,7 @@ func AddRelatedPropertyGeneratorsForService_Spec(gens map[string]gopter.Gen) { gens["ConfigurationApi"] = gen.PtrOf(ConfigurationApiGenerator()) gens["HostnameConfigurations"] = gen.SliceOf(HostnameConfigurationGenerator()) gens["Identity"] = gen.PtrOf(ApiManagementServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServiceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(ApiManagementServiceSkuPropertiesGenerator()) gens["VirtualNetworkConfiguration"] = gen.PtrOf(VirtualNetworkConfigurationGenerator()) } diff --git a/v2/api/apimanagement/v1api20230501preview/storage/structure.txt b/v2/api/apimanagement/v1api20230501preview/storage/structure.txt index 3b0159dd7a8..ca8637f05fb 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/structure.txt +++ b/v2/api/apimanagement/v1api20230501preview/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-05-01-preview" Api: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (29 properties) +├── Spec: Object (30 properties) │ ├── APIVersion: *string │ ├── ApiRevision: *string │ ├── ApiRevisionDescription: *string @@ -52,6 +52,10 @@ Api: Resource │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Url: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Path: *string @@ -136,10 +140,14 @@ Api: Resource └── Type: *string ApiVersionSet: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Description: *string │ ├── DisplayName: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -159,7 +167,7 @@ ApiVersionSet: Resource └── VersioningScheme: *string AuthorizationProvider: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── DisplayName: *string │ ├── IdentityProvider: *string @@ -170,6 +178,10 @@ AuthorizationProvider: Resource │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── RedirectUrl: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -190,10 +202,14 @@ AuthorizationProvider: Resource └── Type: *string AuthorizationProvidersAuthorization: Resource ├── Owner: apimanagement/v1api20230501preview.AuthorizationProvider -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AuthorizationType: *string │ ├── AzureName: string │ ├── Oauth2GrantType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Parameters: *genruntime.SecretMapReference @@ -214,11 +230,15 @@ AuthorizationProvidersAuthorization: Resource └── Type: *string AuthorizationProvidersAuthorizationsAccessPolicy: Resource ├── Owner: apimanagement/v1api20230501preview.AuthorizationProvidersAuthorization -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AppIds: string[] │ ├── AzureName: string │ ├── ObjectId: *string │ ├── ObjectIdFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -235,7 +255,7 @@ AuthorizationProvidersAuthorizationsAccessPolicy: Resource └── Type: *string Backend: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AzureName: string │ ├── CircuitBreaker: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -264,6 +284,10 @@ Backend: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Query: map[string]string[] │ ├── Description: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Pool: *Object (2 properties) @@ -365,7 +389,7 @@ Backend: Resource └── Url: *string NamedValue: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── DisplayName: *string │ ├── KeyVault: *Object (4 properties) @@ -373,6 +397,10 @@ NamedValue: Resource │ │ ├── IdentityClientIdFromConfig: *genruntime.ConfigMapReference │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── SecretIdentifier: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -401,8 +429,12 @@ NamedValue: Resource └── Value: *string Policy: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -417,10 +449,14 @@ Policy: Resource └── Value: *string PolicyFragment: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Description: *string │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -437,11 +473,15 @@ PolicyFragment: Resource └── Value: *string Product: Resource ├── Owner: apimanagement/v1api20230501preview.Service -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── ApprovalRequired: *bool │ ├── AzureName: string │ ├── Description: *string │ ├── DisplayName: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -464,8 +504,12 @@ Product: Resource └── Type: *string ProductApi: Resource ├── Owner: apimanagement/v1api20230501preview.Product -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -474,8 +518,12 @@ ProductApi: Resource └── PropertyBag: genruntime.PropertyBag ProductPolicy: Resource ├── Owner: apimanagement/v1api20230501preview.Product -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── Format: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -490,7 +538,7 @@ ProductPolicy: Resource └── Value: *string Service: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (28 properties) +├── Spec: Object (29 properties) │ ├── AdditionalLocations: Object (8 properties)[] │ │ ├── DisableGateway: *bool │ │ ├── Location: *string @@ -560,6 +608,10 @@ Service: Resource │ ├── Location: *string │ ├── NatGatewayState: *string │ ├── NotificationSenderEmail: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -713,8 +765,10 @@ Subscription: Resource │ ├── AllowTracing: *bool │ ├── AzureName: string │ ├── DisplayName: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── PrimaryKey: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -756,11 +810,13 @@ augmentConversionForApiManagementServiceIdentity: Interface augmentConversionForApiManagementServiceIdentity_STATUS: Interface augmentConversionForApiManagementServiceSkuProperties: Interface augmentConversionForApiManagementServiceSkuProperties_STATUS: Interface +augmentConversionForApiOperatorSpec: Interface augmentConversionForApiVersionConstraint: Interface augmentConversionForApiVersionConstraint_STATUS: Interface augmentConversionForApiVersionSet: Interface augmentConversionForApiVersionSetContractDetails: Interface augmentConversionForApiVersionSetContractDetails_STATUS: Interface +augmentConversionForApiVersionSetOperatorSpec: Interface augmentConversionForApiVersionSet_STATUS: Interface augmentConversionForApiVersionSet_Spec: Interface augmentConversionForApi_STATUS: Interface @@ -774,12 +830,15 @@ augmentConversionForAuthorizationProviderOAuth2GrantTypes: Interface augmentConversionForAuthorizationProviderOAuth2GrantTypes_STATUS: Interface augmentConversionForAuthorizationProviderOAuth2Settings: Interface augmentConversionForAuthorizationProviderOAuth2Settings_STATUS: Interface +augmentConversionForAuthorizationProviderOperatorSpec: Interface augmentConversionForAuthorizationProvider_STATUS: Interface augmentConversionForAuthorizationProvider_Spec: Interface augmentConversionForAuthorizationProvidersAuthorization: Interface +augmentConversionForAuthorizationProvidersAuthorizationOperatorSpec: Interface augmentConversionForAuthorizationProvidersAuthorization_STATUS: Interface augmentConversionForAuthorizationProvidersAuthorization_Spec: Interface augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicy: Interface +augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec: Interface augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicy_STATUS: Interface augmentConversionForAuthorizationProvidersAuthorizationsAccessPolicy_Spec: Interface augmentConversionForBackend: Interface @@ -787,6 +846,7 @@ augmentConversionForBackendAuthorizationHeaderCredentials: Interface augmentConversionForBackendAuthorizationHeaderCredentials_STATUS: Interface augmentConversionForBackendCredentialsContract: Interface augmentConversionForBackendCredentialsContract_STATUS: Interface +augmentConversionForBackendOperatorSpec: Interface augmentConversionForBackendProperties: Interface augmentConversionForBackendProperties_STATUS: Interface augmentConversionForBackendProxyContract: Interface @@ -807,6 +867,7 @@ augmentConversionForKeyVaultContractCreateProperties: Interface augmentConversionForKeyVaultContractProperties_STATUS: Interface augmentConversionForKeyVaultLastAccessStatusContractProperties_STATUS: Interface augmentConversionForNamedValue: Interface +augmentConversionForNamedValueOperatorSpec: Interface augmentConversionForNamedValue_STATUS: Interface augmentConversionForNamedValue_Spec: Interface augmentConversionForOAuth2AuthenticationSettingsContract: Interface @@ -815,22 +876,28 @@ augmentConversionForOpenIdAuthenticationSettingsContract: Interface augmentConversionForOpenIdAuthenticationSettingsContract_STATUS: Interface augmentConversionForPolicy: Interface augmentConversionForPolicyFragment: Interface +augmentConversionForPolicyFragmentOperatorSpec: Interface augmentConversionForPolicyFragment_STATUS: Interface augmentConversionForPolicyFragment_Spec: Interface +augmentConversionForPolicyOperatorSpec: Interface augmentConversionForPolicy_STATUS: Interface augmentConversionForPolicy_Spec: Interface augmentConversionForPrivateLinkServiceConnectionState_STATUS: Interface augmentConversionForProduct: Interface augmentConversionForProductApi: Interface +augmentConversionForProductApiOperatorSpec: Interface augmentConversionForProductApi_STATUS: Interface augmentConversionForProductApi_Spec: Interface +augmentConversionForProductOperatorSpec: Interface augmentConversionForProductPolicy: Interface +augmentConversionForProductPolicyOperatorSpec: Interface augmentConversionForProductPolicy_STATUS: Interface augmentConversionForProductPolicy_Spec: Interface augmentConversionForProduct_STATUS: Interface augmentConversionForProduct_Spec: Interface augmentConversionForRemotePrivateEndpointConnectionWrapper_STATUS: Interface augmentConversionForService: Interface +augmentConversionForServiceOperatorSpec: Interface augmentConversionForService_STATUS: Interface augmentConversionForService_Spec: Interface augmentConversionForSubscription: Interface diff --git a/v2/api/apimanagement/v1api20230501preview/storage/subscription_types_gen.go b/v2/api/apimanagement/v1api20230501preview/storage/subscription_types_gen.go index e12f7db5e57..1a11b8eff93 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/subscription_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/subscription_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/apimanagement/v1api20220801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (subscription *Subscription) ConvertTo(hub conversion.Hub) error { return subscription.AssignProperties_To_Subscription(destination) } +var _ configmaps.Exporter = &Subscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *Subscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Subscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *Subscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Subscription{} // AzureName returns the Azure name of the resource @@ -725,8 +748,10 @@ type augmentConversionForSubscription_STATUS interface { // Storage version of v1api20230501preview.SubscriptionOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SubscriptionOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_SubscriptionOperatorSpec populates our SubscriptionOperatorSpec from the provided source SubscriptionOperatorSpec @@ -734,6 +759,42 @@ func (operator *SubscriptionOperatorSpec) AssignProperties_From_SubscriptionOper // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret SubscriptionOperatorSecrets @@ -771,6 +832,42 @@ func (operator *SubscriptionOperatorSpec) AssignProperties_To_SubscriptionOperat // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.SubscriptionOperatorSecrets diff --git a/v2/api/apimanagement/v1api20230501preview/storage/zz_generated.deepcopy.go b/v2/api/apimanagement/v1api20230501preview/storage/zz_generated.deepcopy.go index 143b7f9f307..a37ffa6166e 100644 --- a/v2/api/apimanagement/v1api20230501preview/storage/zz_generated.deepcopy.go +++ b/v2/api/apimanagement/v1api20230501preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -525,6 +526,50 @@ func (in *ApiManagementServiceSkuProperties_STATUS) DeepCopy() *ApiManagementSer return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiOperatorSpec) DeepCopyInto(out *ApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiOperatorSpec. +func (in *ApiOperatorSpec) DeepCopy() *ApiOperatorSpec { + if in == nil { + return nil + } + out := new(ApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionConstraint) DeepCopyInto(out *ApiVersionConstraint) { *out = *in @@ -742,6 +787,50 @@ func (in *ApiVersionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiVersionSetOperatorSpec) DeepCopyInto(out *ApiVersionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiVersionSetOperatorSpec. +func (in *ApiVersionSetOperatorSpec) DeepCopy() *ApiVersionSetOperatorSpec { + if in == nil { + return nil + } + out := new(ApiVersionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionSet_STATUS) DeepCopyInto(out *ApiVersionSet_STATUS) { *out = *in @@ -824,6 +913,11 @@ func (in *ApiVersionSet_Spec) DeepCopyInto(out *ApiVersionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiVersionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1090,6 +1184,11 @@ func (in *Api_Spec) DeepCopyInto(out *Api_Spec) { *out = new(ApiLicenseInformation) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1511,6 +1610,50 @@ func (in *AuthorizationProviderOAuth2Settings_STATUS) DeepCopy() *AuthorizationP return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProviderOperatorSpec) DeepCopyInto(out *AuthorizationProviderOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProviderOperatorSpec. +func (in *AuthorizationProviderOperatorSpec) DeepCopy() *AuthorizationProviderOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProviderOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvider_STATUS) DeepCopyInto(out *AuthorizationProvider_STATUS) { *out = *in @@ -1588,6 +1731,11 @@ func (in *AuthorizationProvider_Spec) DeepCopyInto(out *AuthorizationProvider_Sp *out = new(AuthorizationProviderOAuth2Settings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProviderOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1671,6 +1819,50 @@ func (in *AuthorizationProvidersAuthorizationList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationOperatorSpec. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorization_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorization_STATUS) { *out = *in @@ -1755,6 +1947,11 @@ func (in *AuthorizationProvidersAuthorization_Spec) DeepCopyInto(out *Authorizat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1843,6 +2040,50 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicyList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) { *out = *in @@ -1920,6 +2161,11 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) DeepCopyInto(ou *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2273,6 +2519,50 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendOperatorSpec) DeepCopyInto(out *BackendOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendOperatorSpec. +func (in *BackendOperatorSpec) DeepCopy() *BackendOperatorSpec { + if in == nil { + return nil + } + out := new(BackendOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendPool) DeepCopyInto(out *BackendPool) { *out = *in @@ -2802,6 +3092,11 @@ func (in *Backend_Spec) DeepCopyInto(out *Backend_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackendOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3653,6 +3948,50 @@ func (in *NamedValueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedValueOperatorSpec) DeepCopyInto(out *NamedValueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedValueOperatorSpec. +func (in *NamedValueOperatorSpec) DeepCopy() *NamedValueOperatorSpec { + if in == nil { + return nil + } + out := new(NamedValueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamedValue_STATUS) DeepCopyInto(out *NamedValue_STATUS) { *out = *in @@ -3740,6 +4079,11 @@ func (in *NamedValue_Spec) DeepCopyInto(out *NamedValue_Spec) { *out = new(KeyVaultContractCreateProperties) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamedValueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3993,6 +4337,50 @@ func (in *PolicyFragmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyFragmentOperatorSpec) DeepCopyInto(out *PolicyFragmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyFragmentOperatorSpec. +func (in *PolicyFragmentOperatorSpec) DeepCopy() *PolicyFragmentOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyFragmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyFragment_STATUS) DeepCopyInto(out *PolicyFragment_STATUS) { *out = *in @@ -4070,6 +4458,11 @@ func (in *PolicyFragment_Spec) DeepCopyInto(out *PolicyFragment_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyFragmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4131,6 +4524,50 @@ func (in *PolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyOperatorSpec) DeepCopyInto(out *PolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyOperatorSpec. +func (in *PolicyOperatorSpec) DeepCopy() *PolicyOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy_STATUS) DeepCopyInto(out *Policy_STATUS) { *out = *in @@ -4193,6 +4630,11 @@ func (in *Policy_Spec) DeepCopyInto(out *Policy_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4345,6 +4787,50 @@ func (in *ProductApiList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductApiOperatorSpec) DeepCopyInto(out *ProductApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductApiOperatorSpec. +func (in *ProductApiOperatorSpec) DeepCopy() *ProductApiOperatorSpec { + if in == nil { + return nil + } + out := new(ProductApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_STATUS) DeepCopyInto(out *ProductApi_STATUS) { *out = *in @@ -4377,6 +4863,11 @@ func (in *ProductApi_STATUS) DeepCopy() *ProductApi_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_Spec) DeepCopyInto(out *ProductApi_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4433,6 +4924,50 @@ func (in *ProductList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductOperatorSpec) DeepCopyInto(out *ProductOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductOperatorSpec. +func (in *ProductOperatorSpec) DeepCopy() *ProductOperatorSpec { + if in == nil { + return nil + } + out := new(ProductOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy) DeepCopyInto(out *ProductPolicy) { *out = *in @@ -4492,6 +5027,50 @@ func (in *ProductPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductPolicyOperatorSpec) DeepCopyInto(out *ProductPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductPolicyOperatorSpec. +func (in *ProductPolicyOperatorSpec) DeepCopy() *ProductPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ProductPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy_STATUS) DeepCopyInto(out *ProductPolicy_STATUS) { *out = *in @@ -4554,6 +5133,11 @@ func (in *ProductPolicy_Spec) DeepCopyInto(out *ProductPolicy_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4680,6 +5264,11 @@ func (in *Product_Spec) DeepCopyInto(out *Product_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4840,6 +5429,50 @@ func (in *ServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceOperatorSpec) DeepCopyInto(out *ServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceOperatorSpec. +func (in *ServiceOperatorSpec) DeepCopy() *ServiceOperatorSpec { + if in == nil { + return nil + } + out := new(ServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service_STATUS) DeepCopyInto(out *Service_STATUS) { *out = *in @@ -5177,6 +5810,11 @@ func (in *Service_Spec) DeepCopyInto(out *Service_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5411,6 +6049,17 @@ func (in *SubscriptionOperatorSecrets) DeepCopy() *SubscriptionOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -5418,6 +6067,17 @@ func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SubscriptionOperatorSecrets) diff --git a/v2/api/apimanagement/v1api20230501preview/structure.txt b/v2/api/apimanagement/v1api20230501preview/structure.txt index e8d8d7a021f..c9cb80e1e0d 100644 --- a/v2/api/apimanagement/v1api20230501preview/structure.txt +++ b/v2/api/apimanagement/v1api20230501preview/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-05-01-preview" Api: Resource ├── Owner: Service -├── Spec: Object (27 properties) +├── Spec: Object (28 properties) │ ├── APIVersion: Validated<*string> (1 rule) │ │ └── Rule 0: MaxLength: 100 │ ├── ApiRevision: Validated<*string> (2 rules) @@ -82,6 +82,9 @@ Api: Resource │ ├── License: *Object (2 properties) │ │ ├── Name: *string │ │ └── Url: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Path: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 400 @@ -185,7 +188,7 @@ Api: Resource └── Type: *string ApiVersionSet: Resource ├── Owner: Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ ├── Rule 1: MinLength: 1 @@ -194,6 +197,9 @@ ApiVersionSet: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── VersionHeaderName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 @@ -220,7 +226,7 @@ ApiVersionSet: Resource └── "Segment" AuthorizationProvider: Resource ├── Owner: Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ ├── Rule 1: MinLength: 1 @@ -234,6 +240,9 @@ AuthorizationProvider: Resource │ │ │ ├── AuthorizationCode: *genruntime.SecretMapReference │ │ │ └── ClientCredentials: *genruntime.SecretMapReference │ │ └── RedirectUrl: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Conditions: conditions.Condition[] @@ -249,7 +258,7 @@ AuthorizationProvider: Resource └── Type: *string AuthorizationProvidersAuthorization: Resource ├── Owner: AuthorizationProvider -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AuthorizationType: *Enum (1 value) │ │ └── "OAuth2" │ ├── AzureName: Validated (3 rules) @@ -259,6 +268,9 @@ AuthorizationProvidersAuthorization: Resource │ ├── Oauth2GrantType: *Enum (2 values) │ │ ├── "AuthorizationCode" │ │ └── "ClientCredentials" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Parameters: *genruntime.SecretMapReference └── Status: Object (9 properties) @@ -278,7 +290,7 @@ AuthorizationProvidersAuthorization: Resource └── Type: *string AuthorizationProvidersAuthorizationsAccessPolicy: Resource ├── Owner: AuthorizationProvidersAuthorization -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AppIds: string[] │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 @@ -286,6 +298,9 @@ AuthorizationProvidersAuthorizationsAccessPolicy: Resource │ │ └── Rule 2: Pattern: "^[^*#&+:<>?]+$" │ ├── ObjectId: *string │ ├── ObjectIdFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── TenantId: *string │ └── TenantIdFromConfig: *genruntime.ConfigMapReference @@ -299,7 +314,7 @@ AuthorizationProvidersAuthorizationsAccessPolicy: Resource └── Type: *string Backend: Resource ├── Owner: Service -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ └── Rule 1: MinLength: 1 @@ -340,6 +355,9 @@ Backend: Resource │ ├── Description: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 2000 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Pool: *Object (1 property) │ │ └── Services: Validated (1 rule) @@ -440,7 +458,7 @@ Backend: Resource └── Url: *string NamedValue: Resource ├── Owner: Service -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ └── Rule 1: Pattern: "^[^*#&+:<>?]+$" @@ -452,6 +470,9 @@ NamedValue: Resource │ │ ├── IdentityClientId: *string │ │ ├── IdentityClientIdFromConfig: *genruntime.ConfigMapReference │ │ └── SecretIdentifier: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Secret: *bool │ ├── Tags: Validated (1 rule) @@ -477,12 +498,15 @@ NamedValue: Resource └── Value: *string Policy: Resource ├── Owner: Service -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── Format: *Enum (4 values) │ │ ├── "rawxml" │ │ ├── "rawxml-link" │ │ ├── "xml" │ │ └── "xml-link" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (6 properties) @@ -498,7 +522,7 @@ Policy: Resource └── Value: *string PolicyFragment: Resource ├── Owner: Service -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 80 │ │ ├── Rule 1: MinLength: 1 @@ -509,6 +533,9 @@ PolicyFragment: Resource │ ├── Format: *Enum (2 values) │ │ ├── "rawxml" │ │ └── "xml" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (8 properties) @@ -524,7 +551,7 @@ PolicyFragment: Resource └── Value: *string Product: Resource ├── Owner: Service -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── ApprovalRequired: *bool │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 256 @@ -535,6 +562,9 @@ Product: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 300 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── State: *Enum (2 values) │ │ ├── "notPublished" @@ -558,22 +588,28 @@ Product: Resource └── Type: *string ProductApi: Resource ├── Owner: Product -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^[^*#&+:<>?]+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (1 property) └── Conditions: conditions.Condition[] ProductPolicy: Resource ├── Owner: Product -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── Format: *Enum (4 values) │ │ ├── "rawxml" │ │ ├── "rawxml-link" │ │ ├── "xml" │ │ └── "xml-link" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Value: *string └── Status: Object (6 properties) @@ -589,7 +625,7 @@ ProductPolicy: Resource └── Value: *string Service: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (26 properties) +├── Spec: Object (27 properties) │ ├── AdditionalLocations: Object (7 properties)[] │ │ ├── DisableGateway: *bool │ │ ├── Location: *string @@ -689,6 +725,9 @@ Service: Resource │ │ └── "Enabled" │ ├── NotificationSenderEmail: Validated<*string> (1 rule) │ │ └── Rule 0: MaxLength: 100 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicIpAddressReference: *genruntime.ResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) @@ -910,7 +949,9 @@ Subscription: Resource │ ├── DisplayName: Validated<*string> (2 rules) │ │ ├── Rule 0: MaxLength: 100 │ │ └── Rule 1: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── PrimaryKey: *genruntime.SecretDestination │ │ └── SecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/apimanagement/v1api20230501preview/subscription_types_gen.go b/v2/api/apimanagement/v1api20230501preview/subscription_types_gen.go index 0c111f06405..7be043812c2 100644 --- a/v2/api/apimanagement/v1api20230501preview/subscription_types_gen.go +++ b/v2/api/apimanagement/v1api20230501preview/subscription_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (subscription *Subscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the Subscription resource func (subscription *Subscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &Subscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *Subscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Subscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *Subscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Subscription{} // AzureName returns the Azure name of the resource @@ -214,7 +236,7 @@ func (subscription *Subscription) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (subscription *Subscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -235,7 +257,18 @@ func (subscription *Subscription) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return subscription.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *Subscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -257,14 +290,14 @@ func (subscription *Subscription) validateSecretDestinations() (admission.Warnin if subscription.Spec.OperatorSpec == nil { return nil, nil } - if subscription.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - subscription.Spec.OperatorSpec.Secrets.PrimaryKey, - subscription.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if subscription.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + subscription.Spec.OperatorSpec.Secrets.PrimaryKey, + subscription.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(subscription, toValidate, subscription.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1198,6 +1231,12 @@ var subscriptionCreateParameterProperties_State_Values = map[string]Subscription // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *SubscriptionOperatorSecrets `json:"secrets,omitempty"` } @@ -1205,6 +1244,42 @@ type SubscriptionOperatorSpec struct { // AssignProperties_From_SubscriptionOperatorSpec populates our SubscriptionOperatorSpec from the provided source SubscriptionOperatorSpec func (operator *SubscriptionOperatorSpec) AssignProperties_From_SubscriptionOperatorSpec(source *storage.SubscriptionOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret SubscriptionOperatorSecrets @@ -1226,6 +1301,42 @@ func (operator *SubscriptionOperatorSpec) AssignProperties_To_SubscriptionOperat // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.SubscriptionOperatorSecrets diff --git a/v2/api/apimanagement/v1api20230501preview/zz_generated.deepcopy.go b/v2/api/apimanagement/v1api20230501preview/zz_generated.deepcopy.go index 26efc570817..7e8df69e506 100644 --- a/v2/api/apimanagement/v1api20230501preview/zz_generated.deepcopy.go +++ b/v2/api/apimanagement/v1api20230501preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230501preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -446,6 +447,43 @@ func (in *ApiManagementServiceSkuProperties_STATUS) DeepCopy() *ApiManagementSer return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiOperatorSpec) DeepCopyInto(out *ApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiOperatorSpec. +func (in *ApiOperatorSpec) DeepCopy() *ApiOperatorSpec { + if in == nil { + return nil + } + out := new(ApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionConstraint) DeepCopyInto(out *ApiVersionConstraint) { *out = *in @@ -635,6 +673,43 @@ func (in *ApiVersionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiVersionSetOperatorSpec) DeepCopyInto(out *ApiVersionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiVersionSetOperatorSpec. +func (in *ApiVersionSetOperatorSpec) DeepCopy() *ApiVersionSetOperatorSpec { + if in == nil { + return nil + } + out := new(ApiVersionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApiVersionSet_STATUS) DeepCopyInto(out *ApiVersionSet_STATUS) { *out = *in @@ -710,6 +785,11 @@ func (in *ApiVersionSet_Spec) DeepCopyInto(out *ApiVersionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiVersionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -962,6 +1042,11 @@ func (in *Api_Spec) DeepCopyInto(out *Api_Spec) { *out = new(ApiLicenseInformation) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1320,6 +1405,43 @@ func (in *AuthorizationProviderOAuth2Settings_STATUS) DeepCopy() *AuthorizationP return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProviderOperatorSpec) DeepCopyInto(out *AuthorizationProviderOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProviderOperatorSpec. +func (in *AuthorizationProviderOperatorSpec) DeepCopy() *AuthorizationProviderOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProviderOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvider_STATUS) DeepCopyInto(out *AuthorizationProvider_STATUS) { *out = *in @@ -1390,6 +1512,11 @@ func (in *AuthorizationProvider_Spec) DeepCopyInto(out *AuthorizationProvider_Sp *out = new(AuthorizationProviderOAuth2Settings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProviderOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1466,6 +1593,43 @@ func (in *AuthorizationProvidersAuthorizationList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationOperatorSpec. +func (in *AuthorizationProvidersAuthorizationOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorization_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorization_STATUS) { *out = *in @@ -1543,6 +1707,11 @@ func (in *AuthorizationProvidersAuthorization_Spec) DeepCopyInto(out *Authorizat *out = new(AuthorizationContractProperties_Oauth2GrantType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1624,6 +1793,43 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicyList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec. +func (in *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) DeepCopy() *AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) DeepCopyInto(out *AuthorizationProvidersAuthorizationsAccessPolicy_STATUS) { *out = *in @@ -1694,6 +1900,11 @@ func (in *AuthorizationProvidersAuthorizationsAccessPolicy_Spec) DeepCopyInto(ou *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AuthorizationProvidersAuthorizationsAccessPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1998,6 +2209,43 @@ func (in *BackendList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendOperatorSpec) DeepCopyInto(out *BackendOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendOperatorSpec. +func (in *BackendOperatorSpec) DeepCopy() *BackendOperatorSpec { + if in == nil { + return nil + } + out := new(BackendOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackendPool) DeepCopyInto(out *BackendPool) { *out = *in @@ -2436,6 +2684,11 @@ func (in *Backend_Spec) DeepCopyInto(out *Backend_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackendOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3161,6 +3414,43 @@ func (in *NamedValueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamedValueOperatorSpec) DeepCopyInto(out *NamedValueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamedValueOperatorSpec. +func (in *NamedValueOperatorSpec) DeepCopy() *NamedValueOperatorSpec { + if in == nil { + return nil + } + out := new(NamedValueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamedValue_STATUS) DeepCopyInto(out *NamedValue_STATUS) { *out = *in @@ -3241,6 +3531,11 @@ func (in *NamedValue_Spec) DeepCopyInto(out *NamedValue_Spec) { *out = new(KeyVaultContractCreateProperties) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamedValueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3459,6 +3754,43 @@ func (in *PolicyFragmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyFragmentOperatorSpec) DeepCopyInto(out *PolicyFragmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyFragmentOperatorSpec. +func (in *PolicyFragmentOperatorSpec) DeepCopy() *PolicyFragmentOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyFragmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PolicyFragment_STATUS) DeepCopyInto(out *PolicyFragment_STATUS) { *out = *in @@ -3529,6 +3861,11 @@ func (in *PolicyFragment_Spec) DeepCopyInto(out *PolicyFragment_Spec) { *out = new(PolicyFragmentContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyFragmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3583,6 +3920,43 @@ func (in *PolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyOperatorSpec) DeepCopyInto(out *PolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyOperatorSpec. +func (in *PolicyOperatorSpec) DeepCopy() *PolicyOperatorSpec { + if in == nil { + return nil + } + out := new(PolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Policy_STATUS) DeepCopyInto(out *Policy_STATUS) { *out = *in @@ -3638,6 +4012,11 @@ func (in *Policy_Spec) DeepCopyInto(out *Policy_Spec) { *out = new(PolicyContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3776,6 +4155,43 @@ func (in *ProductApiList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductApiOperatorSpec) DeepCopyInto(out *ProductApiOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductApiOperatorSpec. +func (in *ProductApiOperatorSpec) DeepCopy() *ProductApiOperatorSpec { + if in == nil { + return nil + } + out := new(ProductApiOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_STATUS) DeepCopyInto(out *ProductApi_STATUS) { *out = *in @@ -3801,6 +4217,11 @@ func (in *ProductApi_STATUS) DeepCopy() *ProductApi_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductApi_Spec) DeepCopyInto(out *ProductApi_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductApiOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3850,6 +4271,43 @@ func (in *ProductList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductOperatorSpec) DeepCopyInto(out *ProductOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductOperatorSpec. +func (in *ProductOperatorSpec) DeepCopy() *ProductOperatorSpec { + if in == nil { + return nil + } + out := new(ProductOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy) DeepCopyInto(out *ProductPolicy) { *out = *in @@ -3909,6 +4367,43 @@ func (in *ProductPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductPolicyOperatorSpec) DeepCopyInto(out *ProductPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductPolicyOperatorSpec. +func (in *ProductPolicyOperatorSpec) DeepCopy() *ProductPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ProductPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProductPolicy_STATUS) DeepCopyInto(out *ProductPolicy_STATUS) { *out = *in @@ -3964,6 +4459,11 @@ func (in *ProductPolicy_Spec) DeepCopyInto(out *ProductPolicy_Spec) { *out = new(PolicyContractProperties_Format) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4076,6 +4576,11 @@ func (in *Product_Spec) DeepCopyInto(out *Product_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProductOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4222,6 +4727,43 @@ func (in *ServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceOperatorSpec) DeepCopyInto(out *ServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceOperatorSpec. +func (in *ServiceOperatorSpec) DeepCopy() *ServiceOperatorSpec { + if in == nil { + return nil + } + out := new(ServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Service_STATUS) DeepCopyInto(out *Service_STATUS) { *out = *in @@ -4552,6 +5094,11 @@ func (in *Service_Spec) DeepCopyInto(out *Service_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4758,6 +5305,28 @@ func (in *SubscriptionOperatorSecrets) DeepCopy() *SubscriptionOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SubscriptionOperatorSpec) DeepCopyInto(out *SubscriptionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SubscriptionOperatorSecrets) diff --git a/v2/api/appconfiguration/v1api20220501/configuration_store_types_gen.go b/v2/api/appconfiguration/v1api20220501/configuration_store_types_gen.go index 69013c2b6d2..13f96cdd4bf 100644 --- a/v2/api/appconfiguration/v1api20220501/configuration_store_types_gen.go +++ b/v2/api/appconfiguration/v1api20220501/configuration_store_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (store *ConfigurationStore) defaultAzureName() { // defaultImpl applies the code generated defaults to the ConfigurationStore resource func (store *ConfigurationStore) defaultImpl() { store.defaultAzureName() } +var _ configmaps.Exporter = &ConfigurationStore{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (store *ConfigurationStore) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if store.Spec.OperatorSpec == nil { + return nil + } + return store.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ConfigurationStore{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (store *ConfigurationStore) SecretDestinationExpressions() []*core.DestinationExpression { + if store.Spec.OperatorSpec == nil { + return nil + } + return store.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ConfigurationStore{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (store *ConfigurationStore) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (store *ConfigurationStore) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){store.validateResourceReferences, store.validateOwnerReference, store.validateSecretDestinations} + return []func() (admission.Warnings, error){store.validateResourceReferences, store.validateOwnerReference, store.validateSecretDestinations, store.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (store *ConfigurationStore) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return store.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return store.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (store *ConfigurationStore) validateConfigMapDestinations() (admission.Warnings, error) { + if store.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(store, nil, store.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,24 +286,24 @@ func (store *ConfigurationStore) validateSecretDestinations() (admission.Warning if store.Spec.OperatorSpec == nil { return nil, nil } - if store.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - store.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - store.Spec.OperatorSpec.Secrets.PrimaryKey, - store.Spec.OperatorSpec.Secrets.PrimaryKeyID, - store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyConnectionString, - store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyKey, - store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyKeyID, - store.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - store.Spec.OperatorSpec.Secrets.SecondaryKey, - store.Spec.OperatorSpec.Secrets.SecondaryKeyID, - store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyConnectionString, - store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyKey, - store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyKeyID, + var toValidate []*genruntime.SecretDestination + if store.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + store.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + store.Spec.OperatorSpec.Secrets.PrimaryKey, + store.Spec.OperatorSpec.Secrets.PrimaryKeyID, + store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyConnectionString, + store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyKey, + store.Spec.OperatorSpec.Secrets.PrimaryReadOnlyKeyID, + store.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + store.Spec.OperatorSpec.Secrets.SecondaryKey, + store.Spec.OperatorSpec.Secrets.SecondaryKeyID, + store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyConnectionString, + store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyKey, + store.Spec.OperatorSpec.Secrets.SecondaryReadOnlyKeyID, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(store, toValidate, store.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1656,6 +1689,12 @@ func (store *ConfigurationStore_STATUS) AssignProperties_To_ConfigurationStore_S // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ConfigurationStoreOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ConfigurationStoreOperatorSecrets `json:"secrets,omitempty"` } @@ -1663,6 +1702,42 @@ type ConfigurationStoreOperatorSpec struct { // AssignProperties_From_ConfigurationStoreOperatorSpec populates our ConfigurationStoreOperatorSpec from the provided source ConfigurationStoreOperatorSpec func (operator *ConfigurationStoreOperatorSpec) AssignProperties_From_ConfigurationStoreOperatorSpec(source *storage.ConfigurationStoreOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ConfigurationStoreOperatorSecrets @@ -1684,6 +1759,42 @@ func (operator *ConfigurationStoreOperatorSpec) AssignProperties_To_Configuratio // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ConfigurationStoreOperatorSecrets diff --git a/v2/api/appconfiguration/v1api20220501/storage/configuration_store_types_gen.go b/v2/api/appconfiguration/v1api20220501/storage/configuration_store_types_gen.go index 24cf9b14b18..8484bb1ad3e 100644 --- a/v2/api/appconfiguration/v1api20220501/storage/configuration_store_types_gen.go +++ b/v2/api/appconfiguration/v1api20220501/storage/configuration_store_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (store *ConfigurationStore) SetConditions(conditions conditions.Conditions) store.Status.Conditions = conditions } +var _ configmaps.Exporter = &ConfigurationStore{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (store *ConfigurationStore) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if store.Spec.OperatorSpec == nil { + return nil + } + return store.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ConfigurationStore{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (store *ConfigurationStore) SecretDestinationExpressions() []*core.DestinationExpression { + if store.Spec.OperatorSpec == nil { + return nil + } + return store.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ConfigurationStore{} // AzureName returns the Azure name of the resource @@ -240,8 +263,10 @@ func (store *ConfigurationStore_STATUS) ConvertStatusTo(destination genruntime.C // Storage version of v1api20220501.ConfigurationStoreOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ConfigurationStoreOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ConfigurationStoreOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ConfigurationStoreOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20220501.EncryptionProperties diff --git a/v2/api/appconfiguration/v1api20220501/storage/structure.txt b/v2/api/appconfiguration/v1api20220501/storage/structure.txt index 65b8981c341..286ab8f32ab 100644 --- a/v2/api/appconfiguration/v1api20220501/storage/structure.txt +++ b/v2/api/appconfiguration/v1api20220501/storage/structure.txt @@ -23,8 +23,10 @@ ConfigurationStore: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (13 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination diff --git a/v2/api/appconfiguration/v1api20220501/storage/zz_generated.deepcopy.go b/v2/api/appconfiguration/v1api20220501/storage/zz_generated.deepcopy.go index c28b6d4f0e0..1f7efdc4d01 100644 --- a/v2/api/appconfiguration/v1api20220501/storage/zz_generated.deepcopy.go +++ b/v2/api/appconfiguration/v1api20220501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -159,6 +160,17 @@ func (in *ConfigurationStoreOperatorSecrets) DeepCopy() *ConfigurationStoreOpera // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigurationStoreOperatorSpec) DeepCopyInto(out *ConfigurationStoreOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -166,6 +178,17 @@ func (in *ConfigurationStoreOperatorSpec) DeepCopyInto(out *ConfigurationStoreOp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ConfigurationStoreOperatorSecrets) diff --git a/v2/api/appconfiguration/v1api20220501/structure.txt b/v2/api/appconfiguration/v1api20220501/structure.txt index e8cd0c352e1..35c7b7a49fc 100644 --- a/v2/api/appconfiguration/v1api20220501/structure.txt +++ b/v2/api/appconfiguration/v1api20220501/structure.txt @@ -28,7 +28,9 @@ ConfigurationStore: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (12 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination diff --git a/v2/api/appconfiguration/v1api20220501/zz_generated.deepcopy.go b/v2/api/appconfiguration/v1api20220501/zz_generated.deepcopy.go index 9be395dd53c..ed91827a40b 100644 --- a/v2/api/appconfiguration/v1api20220501/zz_generated.deepcopy.go +++ b/v2/api/appconfiguration/v1api20220501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -152,6 +153,28 @@ func (in *ConfigurationStoreOperatorSecrets) DeepCopy() *ConfigurationStoreOpera // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConfigurationStoreOperatorSpec) DeepCopyInto(out *ConfigurationStoreOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ConfigurationStoreOperatorSecrets) diff --git a/v2/api/authorization/v1api20200801preview/role_assignment_types_gen.go b/v2/api/authorization/v1api20200801preview/role_assignment_types_gen.go index f3ebe84f444..5fd68d85bb7 100644 --- a/v2/api/authorization/v1api20200801preview/role_assignment_types_gen.go +++ b/v2/api/authorization/v1api20200801preview/role_assignment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -99,6 +101,26 @@ func (assignment *RoleAssignment) Default() { // defaultImpl applies the code generated defaults to the RoleAssignment resource func (assignment *RoleAssignment) defaultImpl() {} +var _ configmaps.Exporter = &RoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *RoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *RoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RoleAssignment{} // AzureName returns the Azure name of the resource @@ -205,7 +227,7 @@ func (assignment *RoleAssignment) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (assignment *RoleAssignment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateSecretDestinations, assignment.validateConfigMapDestinations, assignment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -220,12 +242,26 @@ func (assignment *RoleAssignment) updateValidations() []func(old runtime.Object) return assignment.validateResourceReferences() }, assignment.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assignment *RoleAssignment) validateConfigMapDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assignment *RoleAssignment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assignment.Spec) @@ -244,6 +280,14 @@ func (assignment *RoleAssignment) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assignment *RoleAssignment) validateSecretDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assignment *RoleAssignment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RoleAssignment) @@ -1126,18 +1170,60 @@ func (assignment *RoleAssignment_STATUS) AssignProperties_To_RoleAssignment_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleAssignmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // NamingConvention: The uuid generation technique to use for any role without an explicit AzureName. One of 'stable' or // 'random'. // +kubebuilder:validation:Enum={"random","stable"} NamingConvention *string `json:"namingConvention,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_RoleAssignmentOperatorSpec populates our RoleAssignmentOperatorSpec from the provided source RoleAssignmentOperatorSpec func (operator *RoleAssignmentOperatorSpec) AssignProperties_From_RoleAssignmentOperatorSpec(source *storage.RoleAssignmentOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // NamingConvention operator.NamingConvention = genruntime.ClonePointerToString(source.NamingConvention) + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -1147,9 +1233,45 @@ func (operator *RoleAssignmentOperatorSpec) AssignProperties_To_RoleAssignmentOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // NamingConvention destination.NamingConvention = genruntime.ClonePointerToString(operator.NamingConvention) + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/authorization/v1api20200801preview/storage/role_assignment_types_gen.go b/v2/api/authorization/v1api20200801preview/storage/role_assignment_types_gen.go index e01bee3be40..bb99cce0b31 100644 --- a/v2/api/authorization/v1api20200801preview/storage/role_assignment_types_gen.go +++ b/v2/api/authorization/v1api20200801preview/storage/role_assignment_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/authorization/v1api20220401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (assignment *RoleAssignment) ConvertTo(hub conversion.Hub) error { return assignment.AssignProperties_To_RoleAssignment(destination) } +var _ configmaps.Exporter = &RoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *RoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *RoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RoleAssignment{} // AzureName returns the Azure name of the resource @@ -726,8 +749,10 @@ type augmentConversionForRoleAssignment_STATUS interface { // Storage version of v1api20200801preview.RoleAssignmentOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleAssignmentOperatorSpec struct { - NamingConvention *string `json:"namingConvention,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + NamingConvention *string `json:"namingConvention,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_RoleAssignmentOperatorSpec populates our RoleAssignmentOperatorSpec from the provided source RoleAssignmentOperatorSpec @@ -735,9 +760,45 @@ func (operator *RoleAssignmentOperatorSpec) AssignProperties_From_RoleAssignment // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // NamingConvention operator.NamingConvention = genruntime.ClonePointerToString(source.NamingConvention) + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { operator.PropertyBag = propertyBag @@ -763,9 +824,45 @@ func (operator *RoleAssignmentOperatorSpec) AssignProperties_To_RoleAssignmentOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // NamingConvention destination.NamingConvention = genruntime.ClonePointerToString(operator.NamingConvention) + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/authorization/v1api20200801preview/storage/structure.txt b/v2/api/authorization/v1api20200801preview/storage/structure.txt index 4b7e8665647..f53db8e709e 100644 --- a/v2/api/authorization/v1api20200801preview/storage/structure.txt +++ b/v2/api/authorization/v1api20200801preview/storage/structure.txt @@ -10,9 +10,11 @@ RoleAssignment: Resource │ ├── ConditionVersion: *string │ ├── DelegatedManagedIdentityResourceReference: *genruntime.ResourceReference │ ├── Description: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── NamingConvention: *string -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PrincipalId: *string diff --git a/v2/api/authorization/v1api20200801preview/storage/zz_generated.deepcopy.go b/v2/api/authorization/v1api20200801preview/storage/zz_generated.deepcopy.go index f802f03310c..ce79670eee9 100644 --- a/v2/api/authorization/v1api20200801preview/storage/zz_generated.deepcopy.go +++ b/v2/api/authorization/v1api20200801preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -77,6 +78,17 @@ func (in *RoleAssignmentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) @@ -89,6 +101,17 @@ func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentOperatorSpec. diff --git a/v2/api/authorization/v1api20200801preview/structure.txt b/v2/api/authorization/v1api20200801preview/structure.txt index 2d855035eb3..011eba86dcb 100644 --- a/v2/api/authorization/v1api20200801preview/structure.txt +++ b/v2/api/authorization/v1api20200801preview/structure.txt @@ -10,8 +10,10 @@ RoleAssignment: Resource │ ├── ConditionVersion: *string │ ├── DelegatedManagedIdentityResourceReference: *genruntime.ResourceReference │ ├── Description: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── NamingConvention: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── NamingConvention: *string +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PrincipalId: *string │ ├── PrincipalIdFromConfig: *genruntime.ConfigMapReference diff --git a/v2/api/authorization/v1api20200801preview/zz_generated.deepcopy.go b/v2/api/authorization/v1api20200801preview/zz_generated.deepcopy.go index e4338c96888..9e7fc3d55dd 100644 --- a/v2/api/authorization/v1api20200801preview/zz_generated.deepcopy.go +++ b/v2/api/authorization/v1api20200801preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20200801preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -77,11 +78,33 @@ func (in *RoleAssignmentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) **out = **in } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentOperatorSpec. diff --git a/v2/api/authorization/v1api20220401/role_assignment_types_gen.go b/v2/api/authorization/v1api20220401/role_assignment_types_gen.go index da17ab41a44..57246644b76 100644 --- a/v2/api/authorization/v1api20220401/role_assignment_types_gen.go +++ b/v2/api/authorization/v1api20220401/role_assignment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (assignment *RoleAssignment) Default() { // defaultImpl applies the code generated defaults to the RoleAssignment resource func (assignment *RoleAssignment) defaultImpl() {} +var _ configmaps.Exporter = &RoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *RoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *RoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RoleAssignment{} // InitializeSpec initializes the spec for this resource from the given status @@ -202,7 +224,7 @@ func (assignment *RoleAssignment) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (assignment *RoleAssignment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateSecretDestinations, assignment.validateConfigMapDestinations, assignment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -217,12 +239,26 @@ func (assignment *RoleAssignment) updateValidations() []func(old runtime.Object) return assignment.validateResourceReferences() }, assignment.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assignment *RoleAssignment) validateConfigMapDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assignment *RoleAssignment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assignment.Spec) @@ -241,6 +277,14 @@ func (assignment *RoleAssignment) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assignment *RoleAssignment) validateSecretDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assignment *RoleAssignment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RoleAssignment) @@ -1166,18 +1210,60 @@ func (assignment *RoleAssignment_STATUS) AssignProperties_To_RoleAssignment_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleAssignmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // NamingConvention: The uuid generation technique to use for any role without an explicit AzureName. One of 'stable' or // 'random'. // +kubebuilder:validation:Enum={"random","stable"} NamingConvention *string `json:"namingConvention,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_RoleAssignmentOperatorSpec populates our RoleAssignmentOperatorSpec from the provided source RoleAssignmentOperatorSpec func (operator *RoleAssignmentOperatorSpec) AssignProperties_From_RoleAssignmentOperatorSpec(source *storage.RoleAssignmentOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // NamingConvention operator.NamingConvention = genruntime.ClonePointerToString(source.NamingConvention) + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -1187,9 +1273,45 @@ func (operator *RoleAssignmentOperatorSpec) AssignProperties_To_RoleAssignmentOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // NamingConvention destination.NamingConvention = genruntime.ClonePointerToString(operator.NamingConvention) + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/authorization/v1api20220401/role_definition_types_gen.go b/v2/api/authorization/v1api20220401/role_definition_types_gen.go index 7f094efcfa2..67906d5c8b8 100644 --- a/v2/api/authorization/v1api20220401/role_definition_types_gen.go +++ b/v2/api/authorization/v1api20220401/role_definition_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (definition *RoleDefinition) Default() { // defaultImpl applies the code generated defaults to the RoleDefinition resource func (definition *RoleDefinition) defaultImpl() {} +var _ configmaps.Exporter = &RoleDefinition{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (definition *RoleDefinition) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if definition.Spec.OperatorSpec == nil { + return nil + } + return definition.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleDefinition{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (definition *RoleDefinition) SecretDestinationExpressions() []*core.DestinationExpression { + if definition.Spec.OperatorSpec == nil { + return nil + } + return definition.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RoleDefinition{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (definition *RoleDefinition) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (definition *RoleDefinition) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){definition.validateResourceReferences} + return []func() (admission.Warnings, error){definition.validateResourceReferences, definition.validateSecretDestinations, definition.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -215,7 +238,22 @@ func (definition *RoleDefinition) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return definition.validateResourceReferences() }, - definition.validateWriteOnceProperties} + definition.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return definition.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return definition.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (definition *RoleDefinition) validateConfigMapDestinations() (admission.Warnings, error) { + if definition.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(definition, nil, definition.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -227,6 +265,14 @@ func (definition *RoleDefinition) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (definition *RoleDefinition) validateSecretDestinations() (admission.Warnings, error) { + if definition.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(definition, nil, definition.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (definition *RoleDefinition) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RoleDefinition) @@ -1295,18 +1341,60 @@ func (permission *Permission_STATUS) AssignProperties_To_Permission_STATUS(desti // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleDefinitionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // NamingConvention: The uuid generation technique to use for any role without an explicit AzureName. One of 'stable' or // 'random'. // +kubebuilder:validation:Enum={"random","stable"} NamingConvention *string `json:"namingConvention,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_RoleDefinitionOperatorSpec populates our RoleDefinitionOperatorSpec from the provided source RoleDefinitionOperatorSpec func (operator *RoleDefinitionOperatorSpec) AssignProperties_From_RoleDefinitionOperatorSpec(source *storage.RoleDefinitionOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // NamingConvention operator.NamingConvention = genruntime.ClonePointerToString(source.NamingConvention) + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -1316,9 +1404,45 @@ func (operator *RoleDefinitionOperatorSpec) AssignProperties_To_RoleDefinitionOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // NamingConvention destination.NamingConvention = genruntime.ClonePointerToString(operator.NamingConvention) + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/authorization/v1api20220401/storage/role_assignment_types_gen.go b/v2/api/authorization/v1api20220401/storage/role_assignment_types_gen.go index 915b559650f..5621b35e7fc 100644 --- a/v2/api/authorization/v1api20220401/storage/role_assignment_types_gen.go +++ b/v2/api/authorization/v1api20220401/storage/role_assignment_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (assignment *RoleAssignment) SetConditions(conditions conditions.Conditions assignment.Status.Conditions = conditions } +var _ configmaps.Exporter = &RoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *RoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *RoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RoleAssignment{} // AzureName returns the Azure name of the resource @@ -237,8 +260,10 @@ func (assignment *RoleAssignment_STATUS) ConvertStatusTo(destination genruntime. // Storage version of v1api20220401.RoleAssignmentOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleAssignmentOperatorSpec struct { - NamingConvention *string `json:"namingConvention,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + NamingConvention *string `json:"namingConvention,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } func init() { diff --git a/v2/api/authorization/v1api20220401/storage/role_definition_types_gen.go b/v2/api/authorization/v1api20220401/storage/role_definition_types_gen.go index cf4efbf3066..c923ae0e5e8 100644 --- a/v2/api/authorization/v1api20220401/storage/role_definition_types_gen.go +++ b/v2/api/authorization/v1api20220401/storage/role_definition_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (definition *RoleDefinition) SetConditions(conditions conditions.Conditions definition.Status.Conditions = conditions } +var _ configmaps.Exporter = &RoleDefinition{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (definition *RoleDefinition) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if definition.Spec.OperatorSpec == nil { + return nil + } + return definition.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RoleDefinition{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (definition *RoleDefinition) SecretDestinationExpressions() []*core.DestinationExpression { + if definition.Spec.OperatorSpec == nil { + return nil + } + return definition.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RoleDefinition{} // AzureName returns the Azure name of the resource @@ -241,8 +264,10 @@ type Permission_STATUS struct { // Storage version of v1api20220401.RoleDefinitionOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RoleDefinitionOperatorSpec struct { - NamingConvention *string `json:"namingConvention,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + NamingConvention *string `json:"namingConvention,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } func init() { diff --git a/v2/api/authorization/v1api20220401/storage/structure.txt b/v2/api/authorization/v1api20220401/storage/structure.txt index c6713ef1819..763f95d3b65 100644 --- a/v2/api/authorization/v1api20220401/storage/structure.txt +++ b/v2/api/authorization/v1api20220401/storage/structure.txt @@ -10,9 +10,11 @@ RoleAssignment: Resource │ ├── ConditionVersion: *string │ ├── DelegatedManagedIdentityResourceReference: *genruntime.ResourceReference │ ├── Description: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── NamingConvention: *string -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PrincipalId: *string @@ -43,9 +45,11 @@ RoleDefinition: Resource │ ├── AssignableScopesReferences: genruntime.ResourceReference[] │ ├── AzureName: string │ ├── Description: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── NamingConvention: *string -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── Permissions: Object (5 properties)[] diff --git a/v2/api/authorization/v1api20220401/storage/zz_generated.deepcopy.go b/v2/api/authorization/v1api20220401/storage/zz_generated.deepcopy.go index d5419d58634..4c2d74c3264 100644 --- a/v2/api/authorization/v1api20220401/storage/zz_generated.deepcopy.go +++ b/v2/api/authorization/v1api20220401/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -161,6 +162,17 @@ func (in *RoleAssignmentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) @@ -173,6 +185,17 @@ func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentOperatorSpec. @@ -423,6 +446,17 @@ func (in *RoleDefinitionList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleDefinitionOperatorSpec) DeepCopyInto(out *RoleDefinitionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) @@ -435,6 +469,17 @@ func (in *RoleDefinitionOperatorSpec) DeepCopyInto(out *RoleDefinitionOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleDefinitionOperatorSpec. diff --git a/v2/api/authorization/v1api20220401/structure.txt b/v2/api/authorization/v1api20220401/structure.txt index bb373b20d4a..fde020510b7 100644 --- a/v2/api/authorization/v1api20220401/structure.txt +++ b/v2/api/authorization/v1api20220401/structure.txt @@ -10,8 +10,10 @@ RoleAssignment: Resource │ ├── ConditionVersion: *string │ ├── DelegatedManagedIdentityResourceReference: *genruntime.ResourceReference │ ├── Description: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── NamingConvention: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── NamingConvention: *string +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PrincipalId: *string │ ├── PrincipalIdFromConfig: *genruntime.ConfigMapReference @@ -49,8 +51,10 @@ RoleDefinition: Resource │ ├── AssignableScopesReferences: genruntime.ResourceReference[] │ ├── AzureName: string │ ├── Description: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── NamingConvention: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── NamingConvention: *string +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── Permissions: Object (4 properties)[] │ │ ├── Actions: string[] diff --git a/v2/api/authorization/v1api20220401/zz_generated.deepcopy.go b/v2/api/authorization/v1api20220401/zz_generated.deepcopy.go index a7ebf160480..2bfae0a523c 100644 --- a/v2/api/authorization/v1api20220401/zz_generated.deepcopy.go +++ b/v2/api/authorization/v1api20220401/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220401 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -147,11 +148,33 @@ func (in *RoleAssignmentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleAssignmentOperatorSpec) DeepCopyInto(out *RoleAssignmentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) **out = **in } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentOperatorSpec. @@ -388,11 +411,33 @@ func (in *RoleDefinitionList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RoleDefinitionOperatorSpec) DeepCopyInto(out *RoleDefinitionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.NamingConvention != nil { in, out := &in.NamingConvention, &out.NamingConvention *out = new(string) **out = **in } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleDefinitionOperatorSpec. diff --git a/v2/api/batch/v1api20210101/batch_account_types_gen.go b/v2/api/batch/v1api20210101/batch_account_types_gen.go index 98ecc8ce6f8..5186bcffb94 100644 --- a/v2/api/batch/v1api20210101/batch_account_types_gen.go +++ b/v2/api/batch/v1api20210101/batch_account_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (account *BatchAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the BatchAccount resource func (account *BatchAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &BatchAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *BatchAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BatchAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *BatchAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &BatchAccount{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (account *BatchAccount) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (account *BatchAccount) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference} + return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations, account.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (account *BatchAccount) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return account.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (account *BatchAccount) validateConfigMapDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(account, nil, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (account *BatchAccount) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (account *BatchAccount) validateSecretDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(account, nil, account.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (account *BatchAccount) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BatchAccount) @@ -355,6 +400,10 @@ type BatchAccount_Spec struct { // Location: The region in which to create the account. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BatchAccountOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -530,6 +579,8 @@ func (account *BatchAccount_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne account.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": account.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -677,6 +728,18 @@ func (account *BatchAccount_Spec) AssignProperties_From_BatchAccount_Spec(source // Location account.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BatchAccountOperatorSpec + err := operatorSpec.AssignProperties_From_BatchAccountOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BatchAccountOperatorSpec() to populate field OperatorSpec") + } + account.OperatorSpec = &operatorSpec + } else { + account.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -769,6 +832,18 @@ func (account *BatchAccount_Spec) AssignProperties_To_BatchAccount_Spec(destinat // Location destination.Location = genruntime.ClonePointerToString(account.Location) + // OperatorSpec + if account.OperatorSpec != nil { + var operatorSpec storage.BatchAccountOperatorSpec + err := account.OperatorSpec.AssignProperties_To_BatchAccountOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BatchAccountOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = account.OriginalVersion() @@ -2062,6 +2137,110 @@ func (identity *BatchAccountIdentity_STATUS) AssignProperties_To_BatchAccountIde return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BatchAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BatchAccountOperatorSpec populates our BatchAccountOperatorSpec from the provided source BatchAccountOperatorSpec +func (operator *BatchAccountOperatorSpec) AssignProperties_From_BatchAccountOperatorSpec(source *storage.BatchAccountOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BatchAccountOperatorSpec populates the provided destination BatchAccountOperatorSpec from our BatchAccountOperatorSpec +func (operator *BatchAccountOperatorSpec) AssignProperties_To_BatchAccountOperatorSpec(destination *storage.BatchAccountOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type BatchAccountProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/batch/v1api20210101/batch_account_types_gen_test.go b/v2/api/batch/v1api20210101/batch_account_types_gen_test.go index b6d16191af4..b735093eaa9 100644 --- a/v2/api/batch/v1api20210101/batch_account_types_gen_test.go +++ b/v2/api/batch/v1api20210101/batch_account_types_gen_test.go @@ -707,6 +707,103 @@ func AddIndependentPropertyGeneratorsForBatchAccountIdentity_UserAssignedIdentit gens["PrincipalId"] = gen.PtrOf(gen.AlphaString()) } +func Test_BatchAccountOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BatchAccountOperatorSpec to BatchAccountOperatorSpec via AssignProperties_To_BatchAccountOperatorSpec & AssignProperties_From_BatchAccountOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBatchAccountOperatorSpec, BatchAccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBatchAccountOperatorSpec tests if a specific instance of BatchAccountOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBatchAccountOperatorSpec(subject BatchAccountOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BatchAccountOperatorSpec + err := copied.AssignProperties_To_BatchAccountOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BatchAccountOperatorSpec + err = actual.AssignProperties_From_BatchAccountOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BatchAccountOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BatchAccountOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBatchAccountOperatorSpec, BatchAccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBatchAccountOperatorSpec runs a test to see if a specific instance of BatchAccountOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBatchAccountOperatorSpec(subject BatchAccountOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BatchAccountOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BatchAccountOperatorSpec instances for property testing - lazily instantiated by +// BatchAccountOperatorSpecGenerator() +var batchAccountOperatorSpecGenerator gopter.Gen + +// BatchAccountOperatorSpecGenerator returns a generator of BatchAccountOperatorSpec instances for property testing. +func BatchAccountOperatorSpecGenerator() gopter.Gen { + if batchAccountOperatorSpecGenerator != nil { + return batchAccountOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + batchAccountOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BatchAccountOperatorSpec{}), generators) + + return batchAccountOperatorSpecGenerator +} + func Test_BatchAccount_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -973,6 +1070,7 @@ func AddRelatedPropertyGeneratorsForBatchAccount_Spec(gens map[string]gopter.Gen gens["Encryption"] = gen.PtrOf(EncryptionPropertiesGenerator()) gens["Identity"] = gen.PtrOf(BatchAccountIdentityGenerator()) gens["KeyVaultReference"] = gen.PtrOf(KeyVaultReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BatchAccountOperatorSpecGenerator()) } func Test_EncryptionProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/batch/v1api20210101/storage/batch_account_types_gen.go b/v2/api/batch/v1api20210101/storage/batch_account_types_gen.go index f19e2770955..edd84d19148 100644 --- a/v2/api/batch/v1api20210101/storage/batch_account_types_gen.go +++ b/v2/api/batch/v1api20210101/storage/batch_account_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (account *BatchAccount) SetConditions(conditions conditions.Conditions) { account.Status.Conditions = conditions } +var _ configmaps.Exporter = &BatchAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *BatchAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BatchAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *BatchAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BatchAccount{} // AzureName returns the Azure name of the resource @@ -150,12 +173,13 @@ type BatchAccount_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Encryption *EncryptionProperties `json:"encryption,omitempty"` - Identity *BatchAccountIdentity `json:"identity,omitempty"` - KeyVaultReference *KeyVaultReference `json:"keyVaultReference,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Encryption *EncryptionProperties `json:"encryption,omitempty"` + Identity *BatchAccountIdentity `json:"identity,omitempty"` + KeyVaultReference *KeyVaultReference `json:"keyVaultReference,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *BatchAccountOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -273,6 +297,14 @@ type BatchAccountIdentity_STATUS struct { UserAssignedIdentities map[string]BatchAccountIdentity_UserAssignedIdentities_STATUS `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20210101.BatchAccountOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BatchAccountOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210101.EncryptionProperties // Configures how customer data is encrypted inside the Batch account. By default, accounts are encrypted using a Microsoft // managed key. For additional control, a customer-managed key can be used instead. diff --git a/v2/api/batch/v1api20210101/storage/batch_account_types_gen_test.go b/v2/api/batch/v1api20210101/storage/batch_account_types_gen_test.go index 074a85ec825..8873821c102 100644 --- a/v2/api/batch/v1api20210101/storage/batch_account_types_gen_test.go +++ b/v2/api/batch/v1api20210101/storage/batch_account_types_gen_test.go @@ -411,6 +411,61 @@ func AddIndependentPropertyGeneratorsForBatchAccountIdentity_UserAssignedIdentit gens["PrincipalId"] = gen.PtrOf(gen.AlphaString()) } +func Test_BatchAccountOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BatchAccountOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBatchAccountOperatorSpec, BatchAccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBatchAccountOperatorSpec runs a test to see if a specific instance of BatchAccountOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBatchAccountOperatorSpec(subject BatchAccountOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BatchAccountOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BatchAccountOperatorSpec instances for property testing - lazily instantiated by +// BatchAccountOperatorSpecGenerator() +var batchAccountOperatorSpecGenerator gopter.Gen + +// BatchAccountOperatorSpecGenerator returns a generator of BatchAccountOperatorSpec instances for property testing. +func BatchAccountOperatorSpecGenerator() gopter.Gen { + if batchAccountOperatorSpecGenerator != nil { + return batchAccountOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + batchAccountOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BatchAccountOperatorSpec{}), generators) + + return batchAccountOperatorSpecGenerator +} + func Test_BatchAccount_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -588,6 +643,7 @@ func AddRelatedPropertyGeneratorsForBatchAccount_Spec(gens map[string]gopter.Gen gens["Encryption"] = gen.PtrOf(EncryptionPropertiesGenerator()) gens["Identity"] = gen.PtrOf(BatchAccountIdentityGenerator()) gens["KeyVaultReference"] = gen.PtrOf(KeyVaultReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BatchAccountOperatorSpecGenerator()) } func Test_EncryptionProperties_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/batch/v1api20210101/storage/structure.txt b/v2/api/batch/v1api20210101/storage/structure.txt index 25efe4de524..4cbfc510c25 100644 --- a/v2/api/batch/v1api20210101/storage/structure.txt +++ b/v2/api/batch/v1api20210101/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-01-01" BatchAccount: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutoStorage: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── StorageAccountReference: *genruntime.ResourceReference @@ -27,6 +27,10 @@ BatchAccount: Resource │ │ ├── Reference: *genruntime.ResourceReference │ │ └── Url: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PoolAllocationMode: *string diff --git a/v2/api/batch/v1api20210101/storage/zz_generated.deepcopy.go b/v2/api/batch/v1api20210101/storage/zz_generated.deepcopy.go index e06cb30b8aa..8c1002ef92f 100644 --- a/v2/api/batch/v1api20210101/storage/zz_generated.deepcopy.go +++ b/v2/api/batch/v1api20210101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -243,6 +244,50 @@ func (in *BatchAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BatchAccountOperatorSpec) DeepCopyInto(out *BatchAccountOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchAccountOperatorSpec. +func (in *BatchAccountOperatorSpec) DeepCopy() *BatchAccountOperatorSpec { + if in == nil { + return nil + } + out := new(BatchAccountOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BatchAccount_STATUS) DeepCopyInto(out *BatchAccount_STATUS) { *out = *in @@ -406,6 +451,11 @@ func (in *BatchAccount_Spec) DeepCopyInto(out *BatchAccount_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BatchAccountOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/batch/v1api20210101/structure.txt b/v2/api/batch/v1api20210101/structure.txt index 2e0435f914d..70955c0ee6e 100644 --- a/v2/api/batch/v1api20210101/structure.txt +++ b/v2/api/batch/v1api20210101/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-01-01" BatchAccount: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AutoStorage: *Object (1 property) │ │ └── StorageAccountReference: *genruntime.ResourceReference │ ├── AzureName: Validated (3 rules) @@ -29,6 +29,9 @@ BatchAccount: Resource │ │ ├── Reference: *genruntime.ResourceReference │ │ └── Url: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PoolAllocationMode: *Enum (2 values) │ │ ├── "BatchService" diff --git a/v2/api/batch/v1api20210101/zz_generated.deepcopy.go b/v2/api/batch/v1api20210101/zz_generated.deepcopy.go index 52ad5c4cd86..feaf075833a 100644 --- a/v2/api/batch/v1api20210101/zz_generated.deepcopy.go +++ b/v2/api/batch/v1api20210101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -206,6 +207,43 @@ func (in *BatchAccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BatchAccountOperatorSpec) DeepCopyInto(out *BatchAccountOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchAccountOperatorSpec. +func (in *BatchAccountOperatorSpec) DeepCopy() *BatchAccountOperatorSpec { + if in == nil { + return nil + } + out := new(BatchAccountOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BatchAccount_STATUS) DeepCopyInto(out *BatchAccount_STATUS) { *out = *in @@ -362,6 +400,11 @@ func (in *BatchAccount_Spec) DeepCopyInto(out *BatchAccount_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BatchAccountOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen.go index 45cdf574157..896baeb45b0 100644 --- a/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *RedisFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisFirewallRule resource func (rule *RedisFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *RedisFirewallRule) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (rule *RedisFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,9 +253,23 @@ func (rule *RedisFirewallRule) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *RedisFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *RedisFirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -247,6 +284,14 @@ func (rule *RedisFirewallRule) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *RedisFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *RedisFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisFirewallRule) @@ -337,6 +382,10 @@ type RedisFirewallRule_Spec struct { // EndIP: highest IP address included in the range EndIP *string `json:"endIP,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -399,6 +448,8 @@ func (rule *RedisFirewallRule_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -477,6 +528,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_From_RedisFirewallRule_Spec // EndIP rule.EndIP = genruntime.ClonePointerToString(source.EndIP) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -503,6 +566,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_To_RedisFirewallRule_Spec(d // EndIP destination.EndIP = genruntime.ClonePointerToString(rule.EndIP) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RedisFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RedisFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -722,6 +797,110 @@ func (rule *RedisFirewallRule_STATUS) AssignProperties_To_RedisFirewallRule_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisFirewallRuleOperatorSpec populates our RedisFirewallRuleOperatorSpec from the provided source RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_From_RedisFirewallRuleOperatorSpec(source *storage.RedisFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisFirewallRuleOperatorSpec populates the provided destination RedisFirewallRuleOperatorSpec from our RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_To_RedisFirewallRuleOperatorSpec(destination *storage.RedisFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen_test.go index 8e3b6034d5c..a7c3dbb8d3c 100644 --- a/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20201201/redis_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisFirewallRuleOperatorSpec to RedisFirewallRuleOperatorSpec via AssignProperties_To_RedisFirewallRuleOperatorSpec & AssignProperties_From_RedisFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec tests if a specific instance of RedisFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.RedisFirewallRuleOperatorSpec + err := copied.AssignProperties_To_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisFirewallRuleOperatorSpec + err = actual.AssignProperties_From_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -367,6 +467,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["EndIP"] = gen.PtrOf(gen.AlphaString()) gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20201201/redis_linked_server_types_gen.go b/v2/api/cache/v1api20201201/redis_linked_server_types_gen.go index 33c2fd29f78..a32be0fa35c 100644 --- a/v2/api/cache/v1api20201201/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20201201/redis_linked_server_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (server *RedisLinkedServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisLinkedServer resource func (server *RedisLinkedServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisLinkedServer{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (server *RedisLinkedServer) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (server *RedisLinkedServer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (server *RedisLinkedServer) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return server.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (server *RedisLinkedServer) validateConfigMapDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(server, nil, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (server *RedisLinkedServer) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (server *RedisLinkedServer) validateSecretDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(server, nil, server.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (server *RedisLinkedServer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisLinkedServer) @@ -576,6 +621,10 @@ type RedisLinkedServer_Spec struct { // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -652,6 +701,8 @@ func (server *RedisLinkedServer_Spec) PopulateFromARM(owner genruntime.Arbitrary // no assignment for property "LinkedRedisCacheReference" + // no assignment for property "OperatorSpec" + // Set property "Owner": server.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -740,6 +791,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_From_RedisLinkedServer_Sp server.LinkedRedisCacheReference = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisLinkedServerOperatorSpec + err := operatorSpec.AssignProperties_From_RedisLinkedServerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + server.OperatorSpec = &operatorSpec + } else { + server.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -780,6 +843,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_To_RedisLinkedServer_Spec destination.LinkedRedisCacheReference = nil } + // OperatorSpec + if server.OperatorSpec != nil { + var operatorSpec storage.RedisLinkedServerOperatorSpec + err := server.OperatorSpec.AssignProperties_To_RedisLinkedServerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = server.OriginalVersion() @@ -832,6 +907,110 @@ var redisLinkedServerCreateProperties_ServerRole_Values = map[string]RedisLinked "secondary": RedisLinkedServerCreateProperties_ServerRole_Secondary, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisLinkedServerOperatorSpec populates our RedisLinkedServerOperatorSpec from the provided source RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_From_RedisLinkedServerOperatorSpec(source *storage.RedisLinkedServerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisLinkedServerOperatorSpec populates the provided destination RedisLinkedServerOperatorSpec from our RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_To_RedisLinkedServerOperatorSpec(destination *storage.RedisLinkedServerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RedisLinkedServerProperties_ServerRole_STATUS string const ( diff --git a/v2/api/cache/v1api20201201/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20201201/redis_linked_server_types_gen_test.go index 13b62012868..c4aaa62f3bb 100644 --- a/v2/api/cache/v1api20201201/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20201201/redis_linked_server_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisLinkedServerOperatorSpec to RedisLinkedServerOperatorSpec via AssignProperties_To_RedisLinkedServerOperatorSpec & AssignProperties_From_RedisLinkedServerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec tests if a specific instance of RedisLinkedServerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.RedisLinkedServerOperatorSpec + err := copied.AssignProperties_To_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisLinkedServerOperatorSpec + err = actual.AssignProperties_From_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -251,6 +348,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -260,6 +360,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -270,6 +376,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.OneConstOf(RedisLinkedServerCreateProperties_ServerRole_Primary, RedisLinkedServerCreateProperties_ServerRole_Secondary)) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen.go index d90fa64cbc9..58593892ea7 100644 --- a/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (schedule *RedisPatchSchedule) Default() { // defaultImpl applies the code generated defaults to the RedisPatchSchedule resource func (schedule *RedisPatchSchedule) defaultImpl() {} +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisPatchSchedule{} // AzureName returns the Azure name of the resource (always "default") @@ -205,7 +228,7 @@ func (schedule *RedisPatchSchedule) ValidateUpdate(old runtime.Object) (admissio // createValidations validates the creation of the resource func (schedule *RedisPatchSchedule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference} + return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference, schedule.validateSecretDestinations, schedule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -223,7 +246,21 @@ func (schedule *RedisPatchSchedule) updateValidations() []func(old runtime.Objec func(old runtime.Object) (admission.Warnings, error) { return schedule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (schedule *RedisPatchSchedule) validateConfigMapDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -240,6 +277,14 @@ func (schedule *RedisPatchSchedule) validateResourceReferences() (admission.Warn return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (schedule *RedisPatchSchedule) validateSecretDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (schedule *RedisPatchSchedule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisPatchSchedule) @@ -322,6 +367,10 @@ type RedisPatchScheduleList struct { } type RedisPatchSchedule_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -371,6 +420,8 @@ func (schedule *RedisPatchSchedule_Spec) PopulateFromARM(owner genruntime.Arbitr return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.RedisPatchSchedule_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": schedule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -447,6 +498,18 @@ func (schedule *RedisPatchSchedule_Spec) ConvertSpecTo(destination genruntime.Co // AssignProperties_From_RedisPatchSchedule_Spec populates our RedisPatchSchedule_Spec from the provided source RedisPatchSchedule_Spec func (schedule *RedisPatchSchedule_Spec) AssignProperties_From_RedisPatchSchedule_Spec(source *storage.RedisPatchSchedule_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisPatchScheduleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisPatchScheduleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + schedule.OperatorSpec = &operatorSpec + } else { + schedule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -482,6 +545,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_To_RedisPatchSchedule_ // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if schedule.OperatorSpec != nil { + var operatorSpec storage.RedisPatchScheduleOperatorSpec + err := schedule.OperatorSpec.AssignProperties_To_RedisPatchScheduleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = schedule.OriginalVersion() @@ -744,6 +819,110 @@ func (schedule *RedisPatchSchedule_STATUS) AssignProperties_To_RedisPatchSchedul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisPatchScheduleOperatorSpec populates our RedisPatchScheduleOperatorSpec from the provided source RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_From_RedisPatchScheduleOperatorSpec(source *storage.RedisPatchScheduleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisPatchScheduleOperatorSpec populates the provided destination RedisPatchScheduleOperatorSpec from our RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_To_RedisPatchScheduleOperatorSpec(destination *storage.RedisPatchScheduleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { // +kubebuilder:validation:Required diff --git a/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen_test.go index b4cd659ea0d..e6ccfc1e2b7 100644 --- a/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20201201/redis_patch_schedule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisPatchScheduleOperatorSpec to RedisPatchScheduleOperatorSpec via AssignProperties_To_RedisPatchScheduleOperatorSpec & AssignProperties_From_RedisPatchScheduleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec tests if a specific instance of RedisPatchScheduleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.RedisPatchScheduleOperatorSpec + err := copied.AssignProperties_To_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisPatchScheduleOperatorSpec + err = actual.AssignProperties_From_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,6 +482,7 @@ func RedisPatchSchedule_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20201201/redis_types_gen.go b/v2/api/cache/v1api20201201/redis_types_gen.go index 6972d938ac4..7b8284b9967 100644 --- a/v2/api/cache/v1api20201201/redis_types_gen.go +++ b/v2/api/cache/v1api20201201/redis_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (redis *Redis) defaultAzureName() { // defaultImpl applies the code generated defaults to the Redis resource func (redis *Redis) defaultImpl() { redis.defaultAzureName() } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Redis{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (redis *Redis) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (redis *Redis) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations} + return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations, redis.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (redis *Redis) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return redis.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return redis.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (redis *Redis) validateConfigMapDestinations() (admission.Warnings, error) { + if redis.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(redis, nil, redis.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,17 +289,17 @@ func (redis *Redis) validateSecretDestinations() (admission.Warnings, error) { if redis.Spec.OperatorSpec == nil { return nil, nil } - if redis.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - redis.Spec.OperatorSpec.Secrets.HostName, - redis.Spec.OperatorSpec.Secrets.Port, - redis.Spec.OperatorSpec.Secrets.PrimaryKey, - redis.Spec.OperatorSpec.Secrets.SSLPort, - redis.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if redis.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + redis.Spec.OperatorSpec.Secrets.HostName, + redis.Spec.OperatorSpec.Secrets.Port, + redis.Spec.OperatorSpec.Secrets.PrimaryKey, + redis.Spec.OperatorSpec.Secrets.SSLPort, + redis.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(redis, toValidate, redis.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2394,6 +2427,12 @@ func (server *RedisLinkedServer_STATUS) AssignProperties_To_RedisLinkedServer_ST // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } @@ -2401,6 +2440,42 @@ type RedisOperatorSpec struct { // AssignProperties_From_RedisOperatorSpec populates our RedisOperatorSpec from the provided source RedisOperatorSpec func (operator *RedisOperatorSpec) AssignProperties_From_RedisOperatorSpec(source *storage.RedisOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret RedisOperatorSecrets @@ -2422,6 +2497,42 @@ func (operator *RedisOperatorSpec) AssignProperties_To_RedisOperatorSpec(destina // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.RedisOperatorSecrets diff --git a/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen.go index 8942596fa87..feb51fe5a91 100644 --- a/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (rule *RedisFirewallRule) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisFirewallRule{} // AzureName returns the Azure name of the resource @@ -248,9 +271,10 @@ type augmentConversionForRedisFirewallRule interface { type RedisFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIP *string `json:"endIP,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIP *string `json:"endIP,omitempty"` + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -322,6 +346,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_From_RedisFirewallRule_Spec // EndIP rule.EndIP = genruntime.ClonePointerToString(source.EndIP) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -367,6 +403,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_To_RedisFirewallRule_Spec(d // EndIP destination.EndIP = genruntime.ClonePointerToString(rule.EndIP) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RedisFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RedisFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -558,6 +606,141 @@ type augmentConversionForRedisFirewallRule_STATUS interface { AssignPropertiesTo(dst *storage.RedisFirewallRule_STATUS) error } +// Storage version of v1api20201201.RedisFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisFirewallRuleOperatorSpec populates our RedisFirewallRuleOperatorSpec from the provided source RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_From_RedisFirewallRuleOperatorSpec(source *storage.RedisFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisFirewallRuleOperatorSpec populates the provided destination RedisFirewallRuleOperatorSpec from our RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_To_RedisFirewallRuleOperatorSpec(destination *storage.RedisFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForRedisFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen_test.go index 0180c7e4e88..a417caa0cea 100644 --- a/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20201201/storage/redis_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisFirewallRuleOperatorSpec to RedisFirewallRuleOperatorSpec via AssignProperties_To_RedisFirewallRuleOperatorSpec & AssignProperties_From_RedisFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec tests if a specific instance of RedisFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisFirewallRuleOperatorSpec + err := copied.AssignProperties_To_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisFirewallRuleOperatorSpec + err = actual.AssignProperties_From_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -367,6 +467,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -377,3 +483,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["OriginalVersion"] = gen.AlphaString() gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen.go b/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen.go index 1ca0e9edb81..c210df60516 100644 --- a/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (server *RedisLinkedServer) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisLinkedServer{} // AzureName returns the Azure name of the resource @@ -454,8 +477,9 @@ type RedisLinkedServer_Spec struct { // +kubebuilder:validation:Required // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. - LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -535,6 +559,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_From_RedisLinkedServer_Sp server.LinkedRedisCacheReference = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisLinkedServerOperatorSpec + err := operatorSpec.AssignProperties_From_RedisLinkedServerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + server.OperatorSpec = &operatorSpec + } else { + server.OperatorSpec = nil + } + // OriginalVersion server.OriginalVersion = source.OriginalVersion @@ -588,6 +624,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_To_RedisLinkedServer_Spec destination.LinkedRedisCacheReference = nil } + // OperatorSpec + if server.OperatorSpec != nil { + var operatorSpec storage.RedisLinkedServerOperatorSpec + err := server.OperatorSpec.AssignProperties_To_RedisLinkedServerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = server.OriginalVersion @@ -632,6 +680,141 @@ type augmentConversionForRedisLinkedServer_Spec interface { AssignPropertiesTo(dst *storage.RedisLinkedServer_Spec) error } +// Storage version of v1api20201201.RedisLinkedServerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisLinkedServerOperatorSpec populates our RedisLinkedServerOperatorSpec from the provided source RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_From_RedisLinkedServerOperatorSpec(source *storage.RedisLinkedServerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisLinkedServerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisLinkedServerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisLinkedServerOperatorSpec populates the provided destination RedisLinkedServerOperatorSpec from our RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_To_RedisLinkedServerOperatorSpec(destination *storage.RedisLinkedServerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisLinkedServerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisLinkedServerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForRedisLinkedServerOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisLinkedServerOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisLinkedServerOperatorSpec) error +} + func init() { SchemeBuilder.Register(&RedisLinkedServer{}, &RedisLinkedServerList{}) } diff --git a/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen_test.go index d136f8baa1f..ab4321fa38a 100644 --- a/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20201201/storage/redis_linked_server_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisLinkedServerOperatorSpec to RedisLinkedServerOperatorSpec via AssignProperties_To_RedisLinkedServerOperatorSpec & AssignProperties_From_RedisLinkedServerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec tests if a specific instance of RedisLinkedServerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisLinkedServerOperatorSpec + err := copied.AssignProperties_To_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisLinkedServerOperatorSpec + err = actual.AssignProperties_From_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -251,6 +348,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -260,6 +360,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -271,6 +377,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen.go index 057217e46bd..d5ba03294c6 100644 --- a/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (schedule *RedisPatchSchedule) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisPatchSchedule{} // AzureName returns the Azure name of the resource (always "default") @@ -246,7 +269,8 @@ type augmentConversionForRedisPatchSchedule interface { // Storage version of v1api20201201.RedisPatchSchedule_Spec type RedisPatchSchedule_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -312,6 +336,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_From_RedisPatchSchedul // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisPatchScheduleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisPatchScheduleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + schedule.OperatorSpec = &operatorSpec + } else { + schedule.OperatorSpec = nil + } + // OriginalVersion schedule.OriginalVersion = source.OriginalVersion @@ -366,6 +402,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_To_RedisPatchSchedule_ // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(schedule.PropertyBag) + // OperatorSpec + if schedule.OperatorSpec != nil { + var operatorSpec storage.RedisPatchScheduleOperatorSpec + err := schedule.OperatorSpec.AssignProperties_To_RedisPatchScheduleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = schedule.OriginalVersion @@ -602,6 +650,136 @@ type augmentConversionForRedisPatchSchedule_STATUS interface { AssignPropertiesTo(dst *storage.RedisPatchSchedule_STATUS) error } +// Storage version of v1api20201201.RedisPatchScheduleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisPatchScheduleOperatorSpec populates our RedisPatchScheduleOperatorSpec from the provided source RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_From_RedisPatchScheduleOperatorSpec(source *storage.RedisPatchScheduleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisPatchScheduleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisPatchScheduleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisPatchScheduleOperatorSpec populates the provided destination RedisPatchScheduleOperatorSpec from our RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_To_RedisPatchScheduleOperatorSpec(destination *storage.RedisPatchScheduleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisPatchScheduleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisPatchScheduleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20201201.ScheduleEntry // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { @@ -756,6 +934,11 @@ func (entry *ScheduleEntry_STATUS) AssignProperties_To_ScheduleEntry_STATUS(dest return nil } +type augmentConversionForRedisPatchScheduleOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisPatchScheduleOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisPatchScheduleOperatorSpec) error +} + type augmentConversionForScheduleEntry interface { AssignPropertiesFrom(src *storage.ScheduleEntry) error AssignPropertiesTo(dst *storage.ScheduleEntry) error diff --git a/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen_test.go index 299dcee0b99..111c802f078 100644 --- a/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20201201/storage/redis_patch_schedule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisPatchScheduleOperatorSpec to RedisPatchScheduleOperatorSpec via AssignProperties_To_RedisPatchScheduleOperatorSpec & AssignProperties_From_RedisPatchScheduleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec tests if a specific instance of RedisPatchScheduleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisPatchScheduleOperatorSpec + err := copied.AssignProperties_To_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisPatchScheduleOperatorSpec + err = actual.AssignProperties_From_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,6 +496,7 @@ func AddIndependentPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string] // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20201201/storage/redis_types_gen.go b/v2/api/cache/v1api20201201/storage/redis_types_gen.go index 732d3275b4f..9043b7cfb38 100644 --- a/v2/api/cache/v1api20201201/storage/redis_types_gen.go +++ b/v2/api/cache/v1api20201201/storage/redis_types_gen.go @@ -8,6 +8,9 @@ import ( v20230401s "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -79,6 +82,26 @@ func (redis *Redis) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Redis{} // AzureName returns the Azure name of the resource @@ -1533,8 +1556,10 @@ func (server *RedisLinkedServer_STATUS) AssignProperties_To_RedisLinkedServer_ST // Storage version of v1api20201201.RedisOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_RedisOperatorSpec populates our RedisOperatorSpec from the provided source RedisOperatorSpec @@ -1542,6 +1567,42 @@ func (operator *RedisOperatorSpec) AssignProperties_From_RedisOperatorSpec(sourc // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret RedisOperatorSecrets @@ -1579,6 +1640,42 @@ func (operator *RedisOperatorSpec) AssignProperties_To_RedisOperatorSpec(destina // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20230401s.RedisOperatorSecrets diff --git a/v2/api/cache/v1api20201201/storage/structure.txt b/v2/api/cache/v1api20201201/storage/structure.txt index 6a46b854bbc..8143dc3888b 100644 --- a/v2/api/cache/v1api20201201/storage/structure.txt +++ b/v2/api/cache/v1api20201201/storage/structure.txt @@ -10,8 +10,10 @@ Redis: Resource │ ├── EnableNonSslPort: *bool │ ├── Location: *string │ ├── MinimumTlsVersion: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -113,9 +115,13 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: cache/v1api20201201.Redis -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -130,10 +136,14 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: cache/v1api20201201.Redis -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -150,7 +160,11 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: cache/v1api20201201.Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -175,15 +189,18 @@ augmentConversionForPrivateEndpointConnection_STATUS: Interface augmentConversionForRedis: Interface augmentConversionForRedisCreateProperties_RedisConfiguration: Interface augmentConversionForRedisFirewallRule: Interface +augmentConversionForRedisFirewallRuleOperatorSpec: Interface augmentConversionForRedisFirewallRule_STATUS: Interface augmentConversionForRedisFirewallRule_Spec: Interface augmentConversionForRedisInstanceDetails_STATUS: Interface augmentConversionForRedisLinkedServer: Interface +augmentConversionForRedisLinkedServerOperatorSpec: Interface augmentConversionForRedisLinkedServer_STATUS: Interface augmentConversionForRedisLinkedServer_Spec: Interface augmentConversionForRedisOperatorSecrets: Interface augmentConversionForRedisOperatorSpec: Interface augmentConversionForRedisPatchSchedule: Interface +augmentConversionForRedisPatchScheduleOperatorSpec: Interface augmentConversionForRedisPatchSchedule_STATUS: Interface augmentConversionForRedisPatchSchedule_Spec: Interface augmentConversionForRedisProperties_RedisConfiguration_STATUS: Interface diff --git a/v2/api/cache/v1api20201201/storage/zz_generated.deepcopy.go b/v2/api/cache/v1api20201201/storage/zz_generated.deepcopy.go index 1d44af6d716..d89abb14989 100644 --- a/v2/api/cache/v1api20201201/storage/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20201201/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -217,6 +218,50 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -279,6 +324,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -419,6 +469,50 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -459,6 +553,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -570,6 +669,17 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -577,6 +687,17 @@ func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -653,6 +774,50 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -712,6 +877,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20201201/structure.txt b/v2/api/cache/v1api20201201/structure.txt index db9c7a1a284..381327dbce9 100644 --- a/v2/api/cache/v1api20201201/structure.txt +++ b/v2/api/cache/v1api20201201/structure.txt @@ -13,7 +13,9 @@ Redis: Resource │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -134,9 +136,12 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIP: *string └── Status: Object (6 properties) @@ -148,10 +153,13 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: Redis -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ServerRole: *Enum (2 values) │ ├── "Primary" @@ -169,7 +177,10 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: Redis -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ScheduleEntries: Object (3 properties)[] │ ├── DayOfWeek: *Enum (9 values) diff --git a/v2/api/cache/v1api20201201/zz_generated.deepcopy.go b/v2/api/cache/v1api20201201/zz_generated.deepcopy.go index b87254a6794..4fe23a9c617 100644 --- a/v2/api/cache/v1api20201201/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20201201/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20201201 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -203,6 +204,43 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -258,6 +296,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -384,6 +427,43 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -417,6 +497,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -514,6 +599,28 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -590,6 +697,43 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -642,6 +786,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen.go b/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen.go index 11b5922e7b8..eccdbf2af95 100644 --- a/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen.go +++ b/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *RedisEnterpriseDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisEnterpriseDatabase resource func (database *RedisEnterpriseDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &RedisEnterpriseDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *RedisEnterpriseDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterpriseDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *RedisEnterpriseDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterpriseDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *RedisEnterpriseDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *RedisEnterpriseDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *RedisEnterpriseDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *RedisEnterpriseDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *RedisEnterpriseDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *RedisEnterpriseDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *RedisEnterpriseDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisEnterpriseDatabase) @@ -346,6 +391,10 @@ type RedisEnterpriseDatabase_Spec struct { // Modules: Optional set of redis modules to enable in this database - modules can only be added at creation time. Modules []Module `json:"modules,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisEnterpriseDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -481,6 +530,8 @@ func (database *RedisEnterpriseDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -615,6 +666,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_From_RedisEnterpr database.Modules = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -692,6 +755,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_To_RedisEnterpris destination.Modules = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.RedisEnterpriseDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -1783,6 +1858,110 @@ func (persistence *Persistence_STATUS) AssignProperties_To_Persistence_STATUS(de return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec populates our RedisEnterpriseDatabaseOperatorSpec from the provided source RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source *storage.RedisEnterpriseDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec populates the provided destination RedisEnterpriseDatabaseOperatorSpec from our RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(destination *storage.RedisEnterpriseDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"1s","always"} type Persistence_AofFrequency string diff --git a/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen_test.go b/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen_test.go index 4f5a0935acc..c5343d76158 100644 --- a/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen_test.go +++ b/v2/api/cache/v1api20210301/redis_enterprise_database_types_gen_test.go @@ -583,6 +583,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase(gens map[string]gopt gens["Status"] = RedisEnterpriseDatabase_STATUSGenerator() } +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseDatabaseOperatorSpec to RedisEnterpriseDatabaseOperatorSpec via AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec & AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec tests if a specific instance of RedisEnterpriseDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210301s.RedisEnterpriseDatabaseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseDatabaseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseDatabaseOperatorSpecGenerator() +var redisEnterpriseDatabaseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseDatabaseOperatorSpecGenerator returns a generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing. +func RedisEnterpriseDatabaseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseDatabaseOperatorSpecGenerator != nil { + return redisEnterpriseDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseDatabaseOperatorSpec{}), generators) + + return redisEnterpriseDatabaseOperatorSpecGenerator +} + func Test_RedisEnterpriseDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -862,5 +959,6 @@ func AddIndependentPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[st // AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[string]gopter.Gen) { gens["Modules"] = gen.SliceOf(ModuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseDatabaseOperatorSpecGenerator()) gens["Persistence"] = gen.PtrOf(PersistenceGenerator()) } diff --git a/v2/api/cache/v1api20210301/redis_enterprise_types_gen.go b/v2/api/cache/v1api20210301/redis_enterprise_types_gen.go index ca87f06926f..90cd3ed4890 100644 --- a/v2/api/cache/v1api20210301/redis_enterprise_types_gen.go +++ b/v2/api/cache/v1api20210301/redis_enterprise_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (enterprise *RedisEnterprise) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisEnterprise resource func (enterprise *RedisEnterprise) defaultImpl() { enterprise.defaultAzureName() } +var _ configmaps.Exporter = &RedisEnterprise{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (enterprise *RedisEnterprise) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterprise{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (enterprise *RedisEnterprise) SecretDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterprise{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (enterprise *RedisEnterprise) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (enterprise *RedisEnterprise) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){enterprise.validateResourceReferences, enterprise.validateOwnerReference} + return []func() (admission.Warnings, error){enterprise.validateResourceReferences, enterprise.validateOwnerReference, enterprise.validateSecretDestinations, enterprise.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (enterprise *RedisEnterprise) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return enterprise.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return enterprise.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return enterprise.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (enterprise *RedisEnterprise) validateConfigMapDestinations() (admission.Warnings, error) { + if enterprise.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(enterprise, nil, enterprise.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (enterprise *RedisEnterprise) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (enterprise *RedisEnterprise) validateSecretDestinations() (admission.Warnings, error) { + if enterprise.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(enterprise, nil, enterprise.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (enterprise *RedisEnterprise) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisEnterprise) @@ -345,6 +390,10 @@ type RedisEnterprise_Spec struct { // MinimumTlsVersion: The minimum TLS version for the cluster to support, e.g. '1.2' MinimumTlsVersion *ClusterProperties_MinimumTlsVersion `json:"minimumTlsVersion,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisEnterpriseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -448,6 +497,8 @@ func (enterprise *RedisEnterprise_Spec) PopulateFromARM(owner genruntime.Arbitra } } + // no assignment for property "OperatorSpec" + // Set property "Owner": enterprise.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -550,6 +601,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_From_RedisEnterprise_Sp enterprise.MinimumTlsVersion = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + enterprise.OperatorSpec = &operatorSpec + } else { + enterprise.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -599,6 +662,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_To_RedisEnterprise_Spec destination.MinimumTlsVersion = nil } + // OperatorSpec + if enterprise.OperatorSpec != nil { + var operatorSpec storage.RedisEnterpriseOperatorSpec + err := enterprise.OperatorSpec.AssignProperties_To_RedisEnterpriseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = enterprise.OriginalVersion() @@ -1177,6 +1252,110 @@ var provisioningState_STATUS_Values = map[string]ProvisioningState_STATUS{ "updating": ProvisioningState_STATUS_Updating, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseOperatorSpec populates our RedisEnterpriseOperatorSpec from the provided source RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_From_RedisEnterpriseOperatorSpec(source *storage.RedisEnterpriseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseOperatorSpec populates the provided destination RedisEnterpriseOperatorSpec from our RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_To_RedisEnterpriseOperatorSpec(destination *storage.RedisEnterpriseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Current resource status type ResourceState_STATUS string diff --git a/v2/api/cache/v1api20210301/redis_enterprise_types_gen_test.go b/v2/api/cache/v1api20210301/redis_enterprise_types_gen_test.go index 133bacddf58..492a42d49eb 100644 --- a/v2/api/cache/v1api20210301/redis_enterprise_types_gen_test.go +++ b/v2/api/cache/v1api20210301/redis_enterprise_types_gen_test.go @@ -268,6 +268,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterprise(gens map[string]gopter.Gen) gens["Status"] = RedisEnterprise_STATUSGenerator() } +func Test_RedisEnterpriseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseOperatorSpec to RedisEnterpriseOperatorSpec via AssignProperties_To_RedisEnterpriseOperatorSpec & AssignProperties_From_RedisEnterpriseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec tests if a specific instance of RedisEnterpriseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210301s.RedisEnterpriseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseOperatorSpecGenerator() +var redisEnterpriseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseOperatorSpecGenerator returns a generator of RedisEnterpriseOperatorSpec instances for property testing. +func RedisEnterpriseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseOperatorSpecGenerator != nil { + return redisEnterpriseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseOperatorSpec{}), generators) + + return redisEnterpriseOperatorSpecGenerator +} + func Test_RedisEnterprise_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -536,6 +633,7 @@ func AddIndependentPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForRedisEnterprise_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen.go b/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen.go index c261d239ede..c30329939c0 100644 --- a/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen.go +++ b/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230701/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (database *RedisEnterpriseDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_RedisEnterpriseDatabase(destination) } +var _ configmaps.Exporter = &RedisEnterpriseDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *RedisEnterpriseDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterpriseDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *RedisEnterpriseDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterpriseDatabase{} // AzureName returns the Azure name of the resource @@ -235,12 +258,13 @@ type augmentConversionForRedisEnterpriseDatabase interface { type RedisEnterpriseDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClientProtocol *string `json:"clientProtocol,omitempty"` - ClusteringPolicy *string `json:"clusteringPolicy,omitempty"` - EvictionPolicy *string `json:"evictionPolicy,omitempty"` - Modules []Module `json:"modules,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClientProtocol *string `json:"clientProtocol,omitempty"` + ClusteringPolicy *string `json:"clusteringPolicy,omitempty"` + EvictionPolicy *string `json:"evictionPolicy,omitempty"` + Modules []Module `json:"modules,omitempty"` + OperatorSpec *RedisEnterpriseDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -344,6 +368,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_From_RedisEnterpr database.Modules = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // OriginalVersion database.OriginalVersion = source.OriginalVersion @@ -438,6 +474,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_To_RedisEnterpris destination.Modules = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.RedisEnterpriseDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion @@ -1106,6 +1154,136 @@ func (persistence *Persistence_STATUS) AssignProperties_To_Persistence_STATUS(de return nil } +// Storage version of v1api20210301.RedisEnterpriseDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec populates our RedisEnterpriseDatabaseOperatorSpec from the provided source RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source *storage.RedisEnterpriseDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisEnterpriseDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisEnterpriseDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec populates the provided destination RedisEnterpriseDatabaseOperatorSpec from our RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(destination *storage.RedisEnterpriseDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisEnterpriseDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisEnterpriseDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForModule interface { AssignPropertiesFrom(src *storage.Module) error AssignPropertiesTo(dst *storage.Module) error @@ -1126,6 +1304,11 @@ type augmentConversionForPersistence_STATUS interface { AssignPropertiesTo(dst *storage.Persistence_STATUS) error } +type augmentConversionForRedisEnterpriseDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisEnterpriseDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisEnterpriseDatabaseOperatorSpec) error +} + func init() { SchemeBuilder.Register(&RedisEnterpriseDatabase{}, &RedisEnterpriseDatabaseList{}) } diff --git a/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen_test.go b/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen_test.go index 1791095887f..0d7697be27a 100644 --- a/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen_test.go +++ b/v2/api/cache/v1api20210301/storage/redis_enterprise_database_types_gen_test.go @@ -582,6 +582,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase(gens map[string]gopt gens["Status"] = RedisEnterpriseDatabase_STATUSGenerator() } +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseDatabaseOperatorSpec to RedisEnterpriseDatabaseOperatorSpec via AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec & AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec tests if a specific instance of RedisEnterpriseDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisEnterpriseDatabaseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseDatabaseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseDatabaseOperatorSpecGenerator() +var redisEnterpriseDatabaseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseDatabaseOperatorSpecGenerator returns a generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing. +func RedisEnterpriseDatabaseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseDatabaseOperatorSpecGenerator != nil { + return redisEnterpriseDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseDatabaseOperatorSpec{}), generators) + + return redisEnterpriseDatabaseOperatorSpecGenerator +} + func Test_RedisEnterpriseDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -828,5 +925,6 @@ func AddIndependentPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[st // AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[string]gopter.Gen) { gens["Modules"] = gen.SliceOf(ModuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseDatabaseOperatorSpecGenerator()) gens["Persistence"] = gen.PtrOf(PersistenceGenerator()) } diff --git a/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen.go b/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen.go index 67a692a3bd6..814f7d41c1d 100644 --- a/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen.go +++ b/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen.go @@ -9,6 +9,9 @@ import ( v20230701s "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230701/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -66,6 +69,26 @@ func (enterprise *RedisEnterprise) ConvertTo(hub conversion.Hub) error { return enterprise.AssignProperties_To_RedisEnterprise(destination) } +var _ configmaps.Exporter = &RedisEnterprise{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (enterprise *RedisEnterprise) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterprise{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (enterprise *RedisEnterprise) SecretDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterprise{} // AzureName returns the Azure name of the resource @@ -242,10 +265,11 @@ type augmentConversionForRedisEnterprise interface { type RedisEnterprise_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - MinimumTlsVersion *string `json:"minimumTlsVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + MinimumTlsVersion *string `json:"minimumTlsVersion,omitempty"` + OperatorSpec *RedisEnterpriseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -322,6 +346,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_From_RedisEnterprise_Sp // MinimumTlsVersion enterprise.MinimumTlsVersion = genruntime.ClonePointerToString(source.MinimumTlsVersion) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + enterprise.OperatorSpec = &operatorSpec + } else { + enterprise.OperatorSpec = nil + } + // OriginalVersion enterprise.OriginalVersion = source.OriginalVersion @@ -390,6 +426,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_To_RedisEnterprise_Spec // MinimumTlsVersion destination.MinimumTlsVersion = genruntime.ClonePointerToString(enterprise.MinimumTlsVersion) + // OperatorSpec + if enterprise.OperatorSpec != nil { + var operatorSpec v20230701s.RedisEnterpriseOperatorSpec + err := enterprise.OperatorSpec.AssignProperties_To_RedisEnterpriseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = enterprise.OriginalVersion @@ -788,6 +836,136 @@ func (connection *PrivateEndpointConnection_STATUS) AssignProperties_To_PrivateE return nil } +// Storage version of v1api20210301.RedisEnterpriseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseOperatorSpec populates our RedisEnterpriseOperatorSpec from the provided source RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_From_RedisEnterpriseOperatorSpec(source *v20230701s.RedisEnterpriseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisEnterpriseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisEnterpriseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseOperatorSpec populates the provided destination RedisEnterpriseOperatorSpec from our RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_To_RedisEnterpriseOperatorSpec(destination *v20230701s.RedisEnterpriseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisEnterpriseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisEnterpriseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210301.Sku // SKU parameters supplied to the create RedisEnterprise operation. type Sku struct { @@ -973,6 +1151,11 @@ type augmentConversionForPrivateEndpointConnection_STATUS interface { AssignPropertiesTo(dst *v20230401s.PrivateEndpointConnection_STATUS) error } +type augmentConversionForRedisEnterpriseOperatorSpec interface { + AssignPropertiesFrom(src *v20230701s.RedisEnterpriseOperatorSpec) error + AssignPropertiesTo(dst *v20230701s.RedisEnterpriseOperatorSpec) error +} + type augmentConversionForSku interface { AssignPropertiesFrom(src *v20230401s.Sku) error AssignPropertiesTo(dst *v20230401s.Sku) error diff --git a/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen_test.go b/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen_test.go index 483e9c68d39..fed31f276cb 100644 --- a/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen_test.go +++ b/v2/api/cache/v1api20210301/storage/redis_enterprise_types_gen_test.go @@ -268,6 +268,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterprise(gens map[string]gopter.Gen) gens["Status"] = RedisEnterprise_STATUSGenerator() } +func Test_RedisEnterpriseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseOperatorSpec to RedisEnterpriseOperatorSpec via AssignProperties_To_RedisEnterpriseOperatorSpec & AssignProperties_From_RedisEnterpriseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec tests if a specific instance of RedisEnterpriseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230701s.RedisEnterpriseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseOperatorSpecGenerator() +var redisEnterpriseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseOperatorSpecGenerator returns a generator of RedisEnterpriseOperatorSpec instances for property testing. +func RedisEnterpriseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseOperatorSpecGenerator != nil { + return redisEnterpriseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseOperatorSpec{}), generators) + + return redisEnterpriseOperatorSpecGenerator +} + func Test_RedisEnterprise_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -519,6 +616,7 @@ func AddIndependentPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForRedisEnterprise_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cache/v1api20210301/storage/structure.txt b/v2/api/cache/v1api20210301/storage/structure.txt index 53c60d489cc..3688ab5f084 100644 --- a/v2/api/cache/v1api20210301/storage/structure.txt +++ b/v2/api/cache/v1api20210301/storage/structure.txt @@ -5,10 +5,14 @@ APIVersion: Enum (1 value) └── "2021-03-01" RedisEnterprise: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Location: *string │ ├── MinimumTlsVersion: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -41,7 +45,7 @@ RedisEnterprise: Resource └── Zones: string[] RedisEnterpriseDatabase: Resource ├── Owner: cache/v1api20210301.RedisEnterprise -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: string │ ├── ClientProtocol: *string │ ├── ClusteringPolicy: *string @@ -50,6 +54,10 @@ RedisEnterpriseDatabase: Resource │ │ ├── Args: *string │ │ ├── Name: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Persistence: *Object (5 properties) @@ -90,8 +98,10 @@ augmentConversionForPersistence_STATUS: Interface augmentConversionForPrivateEndpointConnection_STATUS: Interface augmentConversionForRedisEnterprise: Interface augmentConversionForRedisEnterpriseDatabase: Interface +augmentConversionForRedisEnterpriseDatabaseOperatorSpec: Interface augmentConversionForRedisEnterpriseDatabase_STATUS: Interface augmentConversionForRedisEnterpriseDatabase_Spec: Interface +augmentConversionForRedisEnterpriseOperatorSpec: Interface augmentConversionForRedisEnterprise_STATUS: Interface augmentConversionForRedisEnterprise_Spec: Interface augmentConversionForSku: Interface diff --git a/v2/api/cache/v1api20210301/storage/zz_generated.deepcopy.go b/v2/api/cache/v1api20210301/storage/zz_generated.deepcopy.go index 8caff301866..505a0df243d 100644 --- a/v2/api/cache/v1api20210301/storage/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20210301/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -281,6 +282,50 @@ func (in *RedisEnterpriseDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopyInto(out *RedisEnterpriseDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseDatabaseOperatorSpec. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopy() *RedisEnterpriseDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterpriseDatabase_STATUS) DeepCopyInto(out *RedisEnterpriseDatabase_STATUS) { *out = *in @@ -392,6 +437,11 @@ func (in *RedisEnterpriseDatabase_Spec) DeepCopyInto(out *RedisEnterpriseDatabas (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -458,6 +508,50 @@ func (in *RedisEnterpriseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseOperatorSpec) DeepCopyInto(out *RedisEnterpriseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseOperatorSpec. +func (in *RedisEnterpriseOperatorSpec) DeepCopy() *RedisEnterpriseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterprise_STATUS) DeepCopyInto(out *RedisEnterprise_STATUS) { *out = *in @@ -569,6 +663,11 @@ func (in *RedisEnterprise_Spec) DeepCopyInto(out *RedisEnterprise_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20210301/structure.txt b/v2/api/cache/v1api20210301/structure.txt index 5771cc3fb99..fd8bf0f74d1 100644 --- a/v2/api/cache/v1api20210301/structure.txt +++ b/v2/api/cache/v1api20210301/structure.txt @@ -5,13 +5,16 @@ APIVersion: Enum (1 value) └── "2021-03-01" RedisEnterprise: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string │ ├── MinimumTlsVersion: *Enum (3 values) │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sku: *Object (2 properties) │ │ ├── Capacity: *int @@ -73,7 +76,7 @@ RedisEnterprise: Resource └── Zones: string[] RedisEnterpriseDatabase: Resource ├── Owner: RedisEnterprise -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── ClientProtocol: *Enum (2 values) │ │ ├── "Encrypted" @@ -93,6 +96,9 @@ RedisEnterpriseDatabase: Resource │ ├── Modules: Object (2 properties)[] │ │ ├── Args: *string │ │ └── Name: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Persistence: *Object (4 properties) │ │ ├── AofEnabled: *bool diff --git a/v2/api/cache/v1api20210301/zz_generated.deepcopy.go b/v2/api/cache/v1api20210301/zz_generated.deepcopy.go index 96647464af9..4b4b57243ab 100644 --- a/v2/api/cache/v1api20210301/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20210301/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210301 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -246,6 +247,43 @@ func (in *RedisEnterpriseDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopyInto(out *RedisEnterpriseDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseDatabaseOperatorSpec. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopy() *RedisEnterpriseDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterpriseDatabase_STATUS) DeepCopyInto(out *RedisEnterpriseDatabase_STATUS) { *out = *in @@ -350,6 +388,11 @@ func (in *RedisEnterpriseDatabase_Spec) DeepCopyInto(out *RedisEnterpriseDatabas (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -409,6 +452,43 @@ func (in *RedisEnterpriseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseOperatorSpec) DeepCopyInto(out *RedisEnterpriseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseOperatorSpec. +func (in *RedisEnterpriseOperatorSpec) DeepCopy() *RedisEnterpriseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterprise_STATUS) DeepCopyInto(out *RedisEnterprise_STATUS) { *out = *in @@ -513,6 +593,11 @@ func (in *RedisEnterprise_Spec) DeepCopyInto(out *RedisEnterprise_Spec) { *out = new(ClusterProperties_MinimumTlsVersion) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen.go index 89f6a25cd04..09b431a8674 100644 --- a/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *RedisFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisFirewallRule resource func (rule *RedisFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *RedisFirewallRule) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (rule *RedisFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,9 +253,23 @@ func (rule *RedisFirewallRule) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *RedisFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *RedisFirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -247,6 +284,14 @@ func (rule *RedisFirewallRule) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *RedisFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *RedisFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisFirewallRule) @@ -337,6 +382,10 @@ type RedisFirewallRule_Spec struct { // EndIP: highest IP address included in the range EndIP *string `json:"endIP,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -399,6 +448,8 @@ func (rule *RedisFirewallRule_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -477,6 +528,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_From_RedisFirewallRule_Spec // EndIP rule.EndIP = genruntime.ClonePointerToString(source.EndIP) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -503,6 +566,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_To_RedisFirewallRule_Spec(d // EndIP destination.EndIP = genruntime.ClonePointerToString(rule.EndIP) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RedisFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RedisFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -722,6 +797,110 @@ func (rule *RedisFirewallRule_STATUS) AssignProperties_To_RedisFirewallRule_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisFirewallRuleOperatorSpec populates our RedisFirewallRuleOperatorSpec from the provided source RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_From_RedisFirewallRuleOperatorSpec(source *storage.RedisFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisFirewallRuleOperatorSpec populates the provided destination RedisFirewallRuleOperatorSpec from our RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_To_RedisFirewallRuleOperatorSpec(destination *storage.RedisFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen_test.go index 75c72c3b82d..29aadf2a755 100644 --- a/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20230401/redis_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisFirewallRuleOperatorSpec to RedisFirewallRuleOperatorSpec via AssignProperties_To_RedisFirewallRuleOperatorSpec & AssignProperties_From_RedisFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec tests if a specific instance of RedisFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisFirewallRuleOperatorSpec + err := copied.AssignProperties_To_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisFirewallRuleOperatorSpec + err = actual.AssignProperties_From_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -367,6 +467,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["EndIP"] = gen.PtrOf(gen.AlphaString()) gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20230401/redis_linked_server_types_gen.go b/v2/api/cache/v1api20230401/redis_linked_server_types_gen.go index 737a7844be1..c9a125d9e9c 100644 --- a/v2/api/cache/v1api20230401/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20230401/redis_linked_server_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (server *RedisLinkedServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisLinkedServer resource func (server *RedisLinkedServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisLinkedServer{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (server *RedisLinkedServer) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (server *RedisLinkedServer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (server *RedisLinkedServer) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return server.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (server *RedisLinkedServer) validateConfigMapDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(server, nil, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (server *RedisLinkedServer) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (server *RedisLinkedServer) validateSecretDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(server, nil, server.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (server *RedisLinkedServer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisLinkedServer) @@ -614,6 +659,10 @@ type RedisLinkedServer_Spec struct { // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -690,6 +739,8 @@ func (server *RedisLinkedServer_Spec) PopulateFromARM(owner genruntime.Arbitrary // no assignment for property "LinkedRedisCacheReference" + // no assignment for property "OperatorSpec" + // Set property "Owner": server.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -778,6 +829,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_From_RedisLinkedServer_Sp server.LinkedRedisCacheReference = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisLinkedServerOperatorSpec + err := operatorSpec.AssignProperties_From_RedisLinkedServerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + server.OperatorSpec = &operatorSpec + } else { + server.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -818,6 +881,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_To_RedisLinkedServer_Spec destination.LinkedRedisCacheReference = nil } + // OperatorSpec + if server.OperatorSpec != nil { + var operatorSpec storage.RedisLinkedServerOperatorSpec + err := server.OperatorSpec.AssignProperties_To_RedisLinkedServerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = server.OriginalVersion() @@ -870,6 +945,110 @@ var redisLinkedServerCreateProperties_ServerRole_Values = map[string]RedisLinked "secondary": RedisLinkedServerCreateProperties_ServerRole_Secondary, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisLinkedServerOperatorSpec populates our RedisLinkedServerOperatorSpec from the provided source RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_From_RedisLinkedServerOperatorSpec(source *storage.RedisLinkedServerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisLinkedServerOperatorSpec populates the provided destination RedisLinkedServerOperatorSpec from our RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_To_RedisLinkedServerOperatorSpec(destination *storage.RedisLinkedServerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RedisLinkedServerProperties_ServerRole_STATUS string const ( diff --git a/v2/api/cache/v1api20230401/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20230401/redis_linked_server_types_gen_test.go index 77c946e7130..7c891b23d4b 100644 --- a/v2/api/cache/v1api20230401/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20230401/redis_linked_server_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisLinkedServerOperatorSpec to RedisLinkedServerOperatorSpec via AssignProperties_To_RedisLinkedServerOperatorSpec & AssignProperties_From_RedisLinkedServerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec tests if a specific instance of RedisLinkedServerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisLinkedServerOperatorSpec + err := copied.AssignProperties_To_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisLinkedServerOperatorSpec + err = actual.AssignProperties_From_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -251,6 +348,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -260,6 +360,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -270,6 +376,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.OneConstOf(RedisLinkedServerCreateProperties_ServerRole_Primary, RedisLinkedServerCreateProperties_ServerRole_Secondary)) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen.go index 6a1291f1985..f4d29c86c62 100644 --- a/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (schedule *RedisPatchSchedule) Default() { // defaultImpl applies the code generated defaults to the RedisPatchSchedule resource func (schedule *RedisPatchSchedule) defaultImpl() {} +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisPatchSchedule{} // AzureName returns the Azure name of the resource (always "default") @@ -205,7 +228,7 @@ func (schedule *RedisPatchSchedule) ValidateUpdate(old runtime.Object) (admissio // createValidations validates the creation of the resource func (schedule *RedisPatchSchedule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference} + return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference, schedule.validateSecretDestinations, schedule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -223,7 +246,21 @@ func (schedule *RedisPatchSchedule) updateValidations() []func(old runtime.Objec func(old runtime.Object) (admission.Warnings, error) { return schedule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (schedule *RedisPatchSchedule) validateConfigMapDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -240,6 +277,14 @@ func (schedule *RedisPatchSchedule) validateResourceReferences() (admission.Warn return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (schedule *RedisPatchSchedule) validateSecretDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (schedule *RedisPatchSchedule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisPatchSchedule) @@ -322,6 +367,10 @@ type RedisPatchScheduleList struct { } type RedisPatchSchedule_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -371,6 +420,8 @@ func (schedule *RedisPatchSchedule_Spec) PopulateFromARM(owner genruntime.Arbitr return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.RedisPatchSchedule_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": schedule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -447,6 +498,18 @@ func (schedule *RedisPatchSchedule_Spec) ConvertSpecTo(destination genruntime.Co // AssignProperties_From_RedisPatchSchedule_Spec populates our RedisPatchSchedule_Spec from the provided source RedisPatchSchedule_Spec func (schedule *RedisPatchSchedule_Spec) AssignProperties_From_RedisPatchSchedule_Spec(source *storage.RedisPatchSchedule_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisPatchScheduleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisPatchScheduleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + schedule.OperatorSpec = &operatorSpec + } else { + schedule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -482,6 +545,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_To_RedisPatchSchedule_ // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if schedule.OperatorSpec != nil { + var operatorSpec storage.RedisPatchScheduleOperatorSpec + err := schedule.OperatorSpec.AssignProperties_To_RedisPatchScheduleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = schedule.OriginalVersion() @@ -744,6 +819,110 @@ func (schedule *RedisPatchSchedule_STATUS) AssignProperties_To_RedisPatchSchedul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisPatchScheduleOperatorSpec populates our RedisPatchScheduleOperatorSpec from the provided source RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_From_RedisPatchScheduleOperatorSpec(source *storage.RedisPatchScheduleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisPatchScheduleOperatorSpec populates the provided destination RedisPatchScheduleOperatorSpec from our RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_To_RedisPatchScheduleOperatorSpec(destination *storage.RedisPatchScheduleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { // +kubebuilder:validation:Required diff --git a/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen_test.go index f32d4397e3d..272931331e5 100644 --- a/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20230401/redis_patch_schedule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisPatchScheduleOperatorSpec to RedisPatchScheduleOperatorSpec via AssignProperties_To_RedisPatchScheduleOperatorSpec & AssignProperties_From_RedisPatchScheduleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec tests if a specific instance of RedisPatchScheduleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230401s.RedisPatchScheduleOperatorSpec + err := copied.AssignProperties_To_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisPatchScheduleOperatorSpec + err = actual.AssignProperties_From_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,6 +482,7 @@ func RedisPatchSchedule_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20230401/redis_types_gen.go b/v2/api/cache/v1api20230401/redis_types_gen.go index 645c58f90ec..b4cbeeabfae 100644 --- a/v2/api/cache/v1api20230401/redis_types_gen.go +++ b/v2/api/cache/v1api20230401/redis_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (redis *Redis) defaultAzureName() { // defaultImpl applies the code generated defaults to the Redis resource func (redis *Redis) defaultImpl() { redis.defaultAzureName() } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Redis{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (redis *Redis) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (redis *Redis) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations} + return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations, redis.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (redis *Redis) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return redis.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return redis.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (redis *Redis) validateConfigMapDestinations() (admission.Warnings, error) { + if redis.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(redis, nil, redis.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,17 +289,17 @@ func (redis *Redis) validateSecretDestinations() (admission.Warnings, error) { if redis.Spec.OperatorSpec == nil { return nil, nil } - if redis.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - redis.Spec.OperatorSpec.Secrets.HostName, - redis.Spec.OperatorSpec.Secrets.Port, - redis.Spec.OperatorSpec.Secrets.PrimaryKey, - redis.Spec.OperatorSpec.Secrets.SSLPort, - redis.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if redis.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + redis.Spec.OperatorSpec.Secrets.HostName, + redis.Spec.OperatorSpec.Secrets.Port, + redis.Spec.OperatorSpec.Secrets.PrimaryKey, + redis.Spec.OperatorSpec.Secrets.SSLPort, + redis.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(redis, toValidate, redis.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2796,6 +2829,12 @@ func (server *RedisLinkedServer_STATUS) AssignProperties_To_RedisLinkedServer_ST // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } @@ -2803,6 +2842,42 @@ type RedisOperatorSpec struct { // AssignProperties_From_RedisOperatorSpec populates our RedisOperatorSpec from the provided source RedisOperatorSpec func (operator *RedisOperatorSpec) AssignProperties_From_RedisOperatorSpec(source *storage.RedisOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret RedisOperatorSecrets @@ -2824,6 +2899,42 @@ func (operator *RedisOperatorSpec) AssignProperties_To_RedisOperatorSpec(destina // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.RedisOperatorSecrets diff --git a/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen.go index ec6fc945693..0c49e14db95 100644 --- a/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *RedisFirewallRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_RedisFirewallRule(destination) } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisFirewallRule{} // AzureName returns the Azure name of the resource @@ -235,9 +258,10 @@ type augmentConversionForRedisFirewallRule interface { type RedisFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIP *string `json:"endIP,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIP *string `json:"endIP,omitempty"` + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -309,6 +333,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_From_RedisFirewallRule_Spec // EndIP rule.EndIP = genruntime.ClonePointerToString(source.EndIP) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -354,6 +390,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_To_RedisFirewallRule_Spec(d // EndIP destination.EndIP = genruntime.ClonePointerToString(rule.EndIP) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RedisFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RedisFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -545,6 +593,141 @@ type augmentConversionForRedisFirewallRule_STATUS interface { AssignPropertiesTo(dst *storage.RedisFirewallRule_STATUS) error } +// Storage version of v1api20230401.RedisFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisFirewallRuleOperatorSpec populates our RedisFirewallRuleOperatorSpec from the provided source RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_From_RedisFirewallRuleOperatorSpec(source *storage.RedisFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisFirewallRuleOperatorSpec populates the provided destination RedisFirewallRuleOperatorSpec from our RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_To_RedisFirewallRuleOperatorSpec(destination *storage.RedisFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForRedisFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen_test.go index d8449c2694a..bbd9d91045f 100644 --- a/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20230401/storage/redis_firewall_rule_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisFirewallRuleOperatorSpec to RedisFirewallRuleOperatorSpec via AssignProperties_To_RedisFirewallRuleOperatorSpec & AssignProperties_From_RedisFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec tests if a specific instance of RedisFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisFirewallRuleOperatorSpec + err := copied.AssignProperties_To_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisFirewallRuleOperatorSpec + err = actual.AssignProperties_From_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -357,6 +454,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -366,6 +466,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["OriginalVersion"] = gen.AlphaString() gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen.go b/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen.go index e3bed56efd4..376b7a309fa 100644 --- a/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (server *RedisLinkedServer) ConvertTo(hub conversion.Hub) error { return server.AssignProperties_To_RedisLinkedServer(destination) } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisLinkedServer{} // AzureName returns the Azure name of the resource @@ -415,8 +438,9 @@ type RedisLinkedServer_Spec struct { // +kubebuilder:validation:Required // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. - LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -496,6 +520,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_From_RedisLinkedServer_Sp server.LinkedRedisCacheReference = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisLinkedServerOperatorSpec + err := operatorSpec.AssignProperties_From_RedisLinkedServerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + server.OperatorSpec = &operatorSpec + } else { + server.OperatorSpec = nil + } + // OriginalVersion server.OriginalVersion = source.OriginalVersion @@ -549,6 +585,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_To_RedisLinkedServer_Spec destination.LinkedRedisCacheReference = nil } + // OperatorSpec + if server.OperatorSpec != nil { + var operatorSpec storage.RedisLinkedServerOperatorSpec + err := server.OperatorSpec.AssignProperties_To_RedisLinkedServerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = server.OriginalVersion @@ -593,6 +641,141 @@ type augmentConversionForRedisLinkedServer_Spec interface { AssignPropertiesTo(dst *storage.RedisLinkedServer_Spec) error } +// Storage version of v1api20230401.RedisLinkedServerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisLinkedServerOperatorSpec populates our RedisLinkedServerOperatorSpec from the provided source RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_From_RedisLinkedServerOperatorSpec(source *storage.RedisLinkedServerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisLinkedServerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisLinkedServerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisLinkedServerOperatorSpec populates the provided destination RedisLinkedServerOperatorSpec from our RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_To_RedisLinkedServerOperatorSpec(destination *storage.RedisLinkedServerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisLinkedServerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisLinkedServerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForRedisLinkedServerOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisLinkedServerOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisLinkedServerOperatorSpec) error +} + func init() { SchemeBuilder.Register(&RedisLinkedServer{}, &RedisLinkedServerList{}) } diff --git a/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen_test.go index f4fc6595d7b..f1d394df383 100644 --- a/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20230401/storage/redis_linked_server_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisLinkedServerOperatorSpec to RedisLinkedServerOperatorSpec via AssignProperties_To_RedisLinkedServerOperatorSpec & AssignProperties_From_RedisLinkedServerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec tests if a specific instance of RedisLinkedServerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisLinkedServerOperatorSpec + err := copied.AssignProperties_To_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisLinkedServerOperatorSpec + err = actual.AssignProperties_From_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -250,6 +347,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -259,6 +359,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -270,6 +376,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen.go index 496998c2b7e..0d3288dfe98 100644 --- a/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (schedule *RedisPatchSchedule) ConvertTo(hub conversion.Hub) error { return schedule.AssignProperties_To_RedisPatchSchedule(destination) } +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisPatchSchedule{} // AzureName returns the Azure name of the resource (always "default") @@ -233,7 +256,8 @@ type augmentConversionForRedisPatchSchedule interface { // Storage version of v1api20230401.RedisPatchSchedule_Spec type RedisPatchSchedule_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -299,6 +323,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_From_RedisPatchSchedul // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisPatchScheduleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisPatchScheduleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + schedule.OperatorSpec = &operatorSpec + } else { + schedule.OperatorSpec = nil + } + // OriginalVersion schedule.OriginalVersion = source.OriginalVersion @@ -353,6 +389,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_To_RedisPatchSchedule_ // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(schedule.PropertyBag) + // OperatorSpec + if schedule.OperatorSpec != nil { + var operatorSpec storage.RedisPatchScheduleOperatorSpec + err := schedule.OperatorSpec.AssignProperties_To_RedisPatchScheduleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = schedule.OriginalVersion @@ -589,6 +637,136 @@ type augmentConversionForRedisPatchSchedule_STATUS interface { AssignPropertiesTo(dst *storage.RedisPatchSchedule_STATUS) error } +// Storage version of v1api20230401.RedisPatchScheduleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisPatchScheduleOperatorSpec populates our RedisPatchScheduleOperatorSpec from the provided source RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_From_RedisPatchScheduleOperatorSpec(source *storage.RedisPatchScheduleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisPatchScheduleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisPatchScheduleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_RedisPatchScheduleOperatorSpec populates the provided destination RedisPatchScheduleOperatorSpec from our RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_To_RedisPatchScheduleOperatorSpec(destination *storage.RedisPatchScheduleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForRedisPatchScheduleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForRedisPatchScheduleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230401.ScheduleEntry // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { @@ -743,6 +921,11 @@ func (entry *ScheduleEntry_STATUS) AssignProperties_To_ScheduleEntry_STATUS(dest return nil } +type augmentConversionForRedisPatchScheduleOperatorSpec interface { + AssignPropertiesFrom(src *storage.RedisPatchScheduleOperatorSpec) error + AssignPropertiesTo(dst *storage.RedisPatchScheduleOperatorSpec) error +} + type augmentConversionForScheduleEntry interface { AssignPropertiesFrom(src *storage.ScheduleEntry) error AssignPropertiesTo(dst *storage.ScheduleEntry) error diff --git a/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen_test.go index 57947dba201..819102974ff 100644 --- a/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20230401/storage/redis_patch_schedule_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisPatchScheduleOperatorSpec to RedisPatchScheduleOperatorSpec via AssignProperties_To_RedisPatchScheduleOperatorSpec & AssignProperties_From_RedisPatchScheduleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec tests if a specific instance of RedisPatchScheduleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisPatchScheduleOperatorSpec + err := copied.AssignProperties_To_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisPatchScheduleOperatorSpec + err = actual.AssignProperties_From_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -398,6 +495,7 @@ func AddIndependentPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string] // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20230401/storage/redis_types_gen.go b/v2/api/cache/v1api20230401/storage/redis_types_gen.go index b7e2480fef4..90f0ebb03a7 100644 --- a/v2/api/cache/v1api20230401/storage/redis_types_gen.go +++ b/v2/api/cache/v1api20230401/storage/redis_types_gen.go @@ -9,6 +9,9 @@ import ( v20230801s "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -66,6 +69,26 @@ func (redis *Redis) ConvertTo(hub conversion.Hub) error { return redis.AssignProperties_To_Redis(destination) } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Redis{} // AzureName returns the Azure name of the resource @@ -1777,8 +1800,10 @@ func (server *RedisLinkedServer_STATUS) AssignProperties_To_RedisLinkedServer_ST // Storage version of v1api20230401.RedisOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_RedisOperatorSpec populates our RedisOperatorSpec from the provided source RedisOperatorSpec @@ -1786,6 +1811,42 @@ func (operator *RedisOperatorSpec) AssignProperties_From_RedisOperatorSpec(sourc // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret RedisOperatorSecrets @@ -1823,6 +1884,42 @@ func (operator *RedisOperatorSpec) AssignProperties_To_RedisOperatorSpec(destina // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20230801s.RedisOperatorSecrets diff --git a/v2/api/cache/v1api20230401/storage/structure.txt b/v2/api/cache/v1api20230401/storage/structure.txt index 0e831bf3171..8de7df2a368 100644 --- a/v2/api/cache/v1api20230401/storage/structure.txt +++ b/v2/api/cache/v1api20230401/storage/structure.txt @@ -16,8 +16,10 @@ Redis: Resource │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string │ ├── MinimumTlsVersion: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -131,9 +133,13 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: cache/v1api20230401.Redis -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -148,10 +154,14 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: cache/v1api20230401.Redis -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -170,7 +180,11 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: cache/v1api20230401.Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -197,15 +211,18 @@ augmentConversionForPrivateEndpointConnection_STATUS: Interface augmentConversionForRedis: Interface augmentConversionForRedisCreateProperties_RedisConfiguration: Interface augmentConversionForRedisFirewallRule: Interface +augmentConversionForRedisFirewallRuleOperatorSpec: Interface augmentConversionForRedisFirewallRule_STATUS: Interface augmentConversionForRedisFirewallRule_Spec: Interface augmentConversionForRedisInstanceDetails_STATUS: Interface augmentConversionForRedisLinkedServer: Interface +augmentConversionForRedisLinkedServerOperatorSpec: Interface augmentConversionForRedisLinkedServer_STATUS: Interface augmentConversionForRedisLinkedServer_Spec: Interface augmentConversionForRedisOperatorSecrets: Interface augmentConversionForRedisOperatorSpec: Interface augmentConversionForRedisPatchSchedule: Interface +augmentConversionForRedisPatchScheduleOperatorSpec: Interface augmentConversionForRedisPatchSchedule_STATUS: Interface augmentConversionForRedisPatchSchedule_Spec: Interface augmentConversionForRedisProperties_RedisConfiguration_STATUS: Interface diff --git a/v2/api/cache/v1api20230401/storage/zz_generated.deepcopy.go b/v2/api/cache/v1api20230401/storage/zz_generated.deepcopy.go index f34d04eca6f..febd5c30b3c 100644 --- a/v2/api/cache/v1api20230401/storage/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230401/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -298,6 +299,50 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -360,6 +405,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -500,6 +550,50 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -540,6 +634,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -651,6 +750,17 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -658,6 +768,17 @@ func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -734,6 +855,50 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -793,6 +958,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230401/structure.txt b/v2/api/cache/v1api20230401/structure.txt index 130613b7a83..68836b1ada0 100644 --- a/v2/api/cache/v1api20230401/structure.txt +++ b/v2/api/cache/v1api20230401/structure.txt @@ -21,7 +21,9 @@ Redis: Resource │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -156,9 +158,12 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIP: *string └── Status: Object (6 properties) @@ -170,10 +175,13 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: Redis -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ServerRole: *Enum (2 values) │ ├── "Primary" @@ -193,7 +201,10 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: Redis -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ScheduleEntries: Object (3 properties)[] │ ├── DayOfWeek: *Enum (9 values) diff --git a/v2/api/cache/v1api20230401/zz_generated.deepcopy.go b/v2/api/cache/v1api20230401/zz_generated.deepcopy.go index 569d48d932d..3d797444899 100644 --- a/v2/api/cache/v1api20230401/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230401/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230401 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -268,6 +269,43 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -323,6 +361,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -449,6 +492,43 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -482,6 +562,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -579,6 +664,28 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -655,6 +762,43 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -707,6 +851,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen.go b/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen.go index e0be9435039..d871e3459a4 100644 --- a/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen.go +++ b/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *RedisEnterpriseDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisEnterpriseDatabase resource func (database *RedisEnterpriseDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &RedisEnterpriseDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *RedisEnterpriseDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterpriseDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *RedisEnterpriseDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RedisEnterpriseDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *RedisEnterpriseDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *RedisEnterpriseDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *RedisEnterpriseDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *RedisEnterpriseDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *RedisEnterpriseDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *RedisEnterpriseDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *RedisEnterpriseDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisEnterpriseDatabase) @@ -346,6 +391,10 @@ type RedisEnterpriseDatabase_Spec struct { // Modules: Optional set of redis modules to enable in this database - modules can only be added at creation time. Modules []Module `json:"modules,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisEnterpriseDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -504,6 +553,8 @@ func (database *RedisEnterpriseDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -650,6 +701,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_From_RedisEnterpr database.Modules = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -739,6 +802,18 @@ func (database *RedisEnterpriseDatabase_Spec) AssignProperties_To_RedisEnterpris destination.Modules = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.RedisEnterpriseDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -2265,6 +2340,110 @@ func (persistence *Persistence_STATUS) AssignProperties_To_Persistence_STATUS(de return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec populates our RedisEnterpriseDatabaseOperatorSpec from the provided source RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(source *storage.RedisEnterpriseDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec populates the provided destination RedisEnterpriseDatabaseOperatorSpec from our RedisEnterpriseDatabaseOperatorSpec +func (operator *RedisEnterpriseDatabaseOperatorSpec) AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(destination *storage.RedisEnterpriseDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Specifies details of a linked database resource. type LinkedDatabase struct { // Reference: Resource ID of a database resource to link with this database. diff --git a/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen_test.go b/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen_test.go index b5672a9d244..3af5e284c4d 100644 --- a/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen_test.go +++ b/v2/api/cache/v1api20230701/redis_enterprise_database_types_gen_test.go @@ -1021,6 +1021,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase(gens map[string]gopt gens["Status"] = RedisEnterpriseDatabase_STATUSGenerator() } +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseDatabaseOperatorSpec to RedisEnterpriseDatabaseOperatorSpec via AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec & AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec tests if a specific instance of RedisEnterpriseDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisEnterpriseDatabaseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseDatabaseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseDatabaseOperatorSpecGenerator() +var redisEnterpriseDatabaseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseDatabaseOperatorSpecGenerator returns a generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing. +func RedisEnterpriseDatabaseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseDatabaseOperatorSpecGenerator != nil { + return redisEnterpriseDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseDatabaseOperatorSpec{}), generators) + + return redisEnterpriseDatabaseOperatorSpecGenerator +} + func Test_RedisEnterpriseDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1302,5 +1399,6 @@ func AddIndependentPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[st func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[string]gopter.Gen) { gens["GeoReplication"] = gen.PtrOf(DatabaseProperties_GeoReplicationGenerator()) gens["Modules"] = gen.SliceOf(ModuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseDatabaseOperatorSpecGenerator()) gens["Persistence"] = gen.PtrOf(PersistenceGenerator()) } diff --git a/v2/api/cache/v1api20230701/redis_enterprise_types_gen.go b/v2/api/cache/v1api20230701/redis_enterprise_types_gen.go index bcdfded3aef..fc85e9bf022 100644 --- a/v2/api/cache/v1api20230701/redis_enterprise_types_gen.go +++ b/v2/api/cache/v1api20230701/redis_enterprise_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (enterprise *RedisEnterprise) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisEnterprise resource func (enterprise *RedisEnterprise) defaultImpl() { enterprise.defaultAzureName() } +var _ configmaps.Exporter = &RedisEnterprise{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (enterprise *RedisEnterprise) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterprise{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (enterprise *RedisEnterprise) SecretDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RedisEnterprise{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (enterprise *RedisEnterprise) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (enterprise *RedisEnterprise) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){enterprise.validateResourceReferences, enterprise.validateOwnerReference} + return []func() (admission.Warnings, error){enterprise.validateResourceReferences, enterprise.validateOwnerReference, enterprise.validateSecretDestinations, enterprise.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (enterprise *RedisEnterprise) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return enterprise.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return enterprise.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return enterprise.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (enterprise *RedisEnterprise) validateConfigMapDestinations() (admission.Warnings, error) { + if enterprise.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(enterprise, nil, enterprise.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (enterprise *RedisEnterprise) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (enterprise *RedisEnterprise) validateSecretDestinations() (admission.Warnings, error) { + if enterprise.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(enterprise, nil, enterprise.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (enterprise *RedisEnterprise) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisEnterprise) @@ -342,6 +387,10 @@ type RedisEnterprise_Spec struct { // MinimumTlsVersion: The minimum TLS version for the cluster to support, e.g. '1.2' MinimumTlsVersion *ClusterProperties_MinimumTlsVersion `json:"minimumTlsVersion,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisEnterpriseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -445,6 +494,8 @@ func (enterprise *RedisEnterprise_Spec) PopulateFromARM(owner genruntime.Arbitra } } + // no assignment for property "OperatorSpec" + // Set property "Owner": enterprise.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -547,6 +598,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_From_RedisEnterprise_Sp enterprise.MinimumTlsVersion = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisEnterpriseOperatorSpec + err := operatorSpec.AssignProperties_From_RedisEnterpriseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + enterprise.OperatorSpec = &operatorSpec + } else { + enterprise.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -596,6 +659,18 @@ func (enterprise *RedisEnterprise_Spec) AssignProperties_To_RedisEnterprise_Spec destination.MinimumTlsVersion = nil } + // OperatorSpec + if enterprise.OperatorSpec != nil { + var operatorSpec storage.RedisEnterpriseOperatorSpec + err := enterprise.OperatorSpec.AssignProperties_To_RedisEnterpriseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisEnterpriseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = enterprise.OriginalVersion() @@ -1210,6 +1285,110 @@ var provisioningState_STATUS_Values = map[string]ProvisioningState_STATUS{ "updating": ProvisioningState_STATUS_Updating, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisEnterpriseOperatorSpec populates our RedisEnterpriseOperatorSpec from the provided source RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_From_RedisEnterpriseOperatorSpec(source *storage.RedisEnterpriseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisEnterpriseOperatorSpec populates the provided destination RedisEnterpriseOperatorSpec from our RedisEnterpriseOperatorSpec +func (operator *RedisEnterpriseOperatorSpec) AssignProperties_To_RedisEnterpriseOperatorSpec(destination *storage.RedisEnterpriseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Current resource status type ResourceState_STATUS string diff --git a/v2/api/cache/v1api20230701/redis_enterprise_types_gen_test.go b/v2/api/cache/v1api20230701/redis_enterprise_types_gen_test.go index c71d4cf30eb..7624f28e090 100644 --- a/v2/api/cache/v1api20230701/redis_enterprise_types_gen_test.go +++ b/v2/api/cache/v1api20230701/redis_enterprise_types_gen_test.go @@ -267,6 +267,103 @@ func AddRelatedPropertyGeneratorsForRedisEnterprise(gens map[string]gopter.Gen) gens["Status"] = RedisEnterprise_STATUSGenerator() } +func Test_RedisEnterpriseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisEnterpriseOperatorSpec to RedisEnterpriseOperatorSpec via AssignProperties_To_RedisEnterpriseOperatorSpec & AssignProperties_From_RedisEnterpriseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec tests if a specific instance of RedisEnterpriseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisEnterpriseOperatorSpec + err := copied.AssignProperties_To_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisEnterpriseOperatorSpec + err = actual.AssignProperties_From_RedisEnterpriseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisEnterpriseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseOperatorSpecGenerator() +var redisEnterpriseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseOperatorSpecGenerator returns a generator of RedisEnterpriseOperatorSpec instances for property testing. +func RedisEnterpriseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseOperatorSpecGenerator != nil { + return redisEnterpriseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseOperatorSpec{}), generators) + + return redisEnterpriseOperatorSpecGenerator +} + func Test_RedisEnterprise_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -535,6 +632,7 @@ func AddIndependentPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForRedisEnterprise_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen.go b/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen.go index e34bc11c20a..07d13d4afb1 100644 --- a/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen.go +++ b/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *RedisEnterpriseDatabase) SetConditions(conditions conditions.Con database.Status.Conditions = conditions } +var _ configmaps.Exporter = &RedisEnterpriseDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *RedisEnterpriseDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterpriseDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *RedisEnterpriseDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterpriseDatabase{} // AzureName returns the Azure name of the resource @@ -142,13 +165,14 @@ type RedisEnterpriseDatabaseList struct { type RedisEnterpriseDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClientProtocol *string `json:"clientProtocol,omitempty"` - ClusteringPolicy *string `json:"clusteringPolicy,omitempty"` - EvictionPolicy *string `json:"evictionPolicy,omitempty"` - GeoReplication *DatabaseProperties_GeoReplication `json:"geoReplication,omitempty"` - Modules []Module `json:"modules,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClientProtocol *string `json:"clientProtocol,omitempty"` + ClusteringPolicy *string `json:"clusteringPolicy,omitempty"` + EvictionPolicy *string `json:"evictionPolicy,omitempty"` + GeoReplication *DatabaseProperties_GeoReplication `json:"geoReplication,omitempty"` + Modules []Module `json:"modules,omitempty"` + OperatorSpec *RedisEnterpriseDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -269,6 +293,14 @@ type Persistence_STATUS struct { RdbFrequency *string `json:"rdbFrequency,omitempty"` } +// Storage version of v1api20230701.RedisEnterpriseDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230701.LinkedDatabase // Specifies details of a linked database resource. type LinkedDatabase struct { diff --git a/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen_test.go b/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen_test.go index 07fa28800d8..786d68f5899 100644 --- a/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen_test.go +++ b/v2/api/cache/v1api20230701/storage/redis_enterprise_database_types_gen_test.go @@ -594,6 +594,61 @@ func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase(gens map[string]gopt gens["Status"] = RedisEnterpriseDatabase_STATUSGenerator() } +func Test_RedisEnterpriseDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec, RedisEnterpriseDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseDatabaseOperatorSpec(subject RedisEnterpriseDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseDatabaseOperatorSpecGenerator() +var redisEnterpriseDatabaseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseDatabaseOperatorSpecGenerator returns a generator of RedisEnterpriseDatabaseOperatorSpec instances for property testing. +func RedisEnterpriseDatabaseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseDatabaseOperatorSpecGenerator != nil { + return redisEnterpriseDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseDatabaseOperatorSpec{}), generators) + + return redisEnterpriseDatabaseOperatorSpecGenerator +} + func Test_RedisEnterpriseDatabase_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -758,5 +813,6 @@ func AddIndependentPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[st func AddRelatedPropertyGeneratorsForRedisEnterpriseDatabase_Spec(gens map[string]gopter.Gen) { gens["GeoReplication"] = gen.PtrOf(DatabaseProperties_GeoReplicationGenerator()) gens["Modules"] = gen.SliceOf(ModuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseDatabaseOperatorSpecGenerator()) gens["Persistence"] = gen.PtrOf(PersistenceGenerator()) } diff --git a/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen.go b/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen.go index b0fc8e6e11b..bede66e6133 100644 --- a/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen.go +++ b/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cache/v1api20230801/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (enterprise *RedisEnterprise) SetConditions(conditions conditions.Condition enterprise.Status.Conditions = conditions } +var _ configmaps.Exporter = &RedisEnterprise{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (enterprise *RedisEnterprise) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisEnterprise{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (enterprise *RedisEnterprise) SecretDestinationExpressions() []*core.DestinationExpression { + if enterprise.Spec.OperatorSpec == nil { + return nil + } + return enterprise.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisEnterprise{} // AzureName returns the Azure name of the resource @@ -149,10 +172,11 @@ const APIVersion_Value = APIVersion("2023-07-01") type RedisEnterprise_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - MinimumTlsVersion *string `json:"minimumTlsVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + MinimumTlsVersion *string `json:"minimumTlsVersion,omitempty"` + OperatorSpec *RedisEnterpriseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -287,6 +311,14 @@ func (connection *PrivateEndpointConnection_STATUS) AssignProperties_To_PrivateE return nil } +// Storage version of v1api20230701.RedisEnterpriseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisEnterpriseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230701.Sku // SKU parameters supplied to the create RedisEnterprise operation. type Sku struct { diff --git a/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen_test.go b/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen_test.go index 32b0015be8c..9e7cd9ef9fa 100644 --- a/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen_test.go +++ b/v2/api/cache/v1api20230701/storage/redis_enterprise_types_gen_test.go @@ -182,6 +182,61 @@ func AddRelatedPropertyGeneratorsForRedisEnterprise(gens map[string]gopter.Gen) gens["Status"] = RedisEnterprise_STATUSGenerator() } +func Test_RedisEnterpriseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisEnterpriseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisEnterpriseOperatorSpec, RedisEnterpriseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisEnterpriseOperatorSpec runs a test to see if a specific instance of RedisEnterpriseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisEnterpriseOperatorSpec(subject RedisEnterpriseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisEnterpriseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisEnterpriseOperatorSpec instances for property testing - lazily instantiated by +// RedisEnterpriseOperatorSpecGenerator() +var redisEnterpriseOperatorSpecGenerator gopter.Gen + +// RedisEnterpriseOperatorSpecGenerator returns a generator of RedisEnterpriseOperatorSpec instances for property testing. +func RedisEnterpriseOperatorSpecGenerator() gopter.Gen { + if redisEnterpriseOperatorSpecGenerator != nil { + return redisEnterpriseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisEnterpriseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisEnterpriseOperatorSpec{}), generators) + + return redisEnterpriseOperatorSpecGenerator +} + func Test_RedisEnterprise_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -349,6 +404,7 @@ func AddIndependentPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForRedisEnterprise_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisEnterprise_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisEnterpriseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cache/v1api20230701/storage/structure.txt b/v2/api/cache/v1api20230701/storage/structure.txt index 05012393f70..9d9bc13d77d 100644 --- a/v2/api/cache/v1api20230701/storage/structure.txt +++ b/v2/api/cache/v1api20230701/storage/structure.txt @@ -5,10 +5,14 @@ APIVersion: Enum (1 value) └── "2023-07-01" RedisEnterprise: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Location: *string │ ├── MinimumTlsVersion: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -41,7 +45,7 @@ RedisEnterprise: Resource └── Zones: string[] RedisEnterpriseDatabase: Resource ├── Owner: cache/v1api20230701.RedisEnterprise -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── ClientProtocol: *string │ ├── ClusteringPolicy: *string @@ -56,6 +60,10 @@ RedisEnterpriseDatabase: Resource │ │ ├── Args: *string │ │ ├── Name: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Persistence: *Object (5 properties) diff --git a/v2/api/cache/v1api20230701/storage/zz_generated.deepcopy.go b/v2/api/cache/v1api20230701/storage/zz_generated.deepcopy.go index 7cea04b07f0..d91356f27dc 100644 --- a/v2/api/cache/v1api20230701/storage/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230701/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -408,6 +409,50 @@ func (in *RedisEnterpriseDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopyInto(out *RedisEnterpriseDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseDatabaseOperatorSpec. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopy() *RedisEnterpriseDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterpriseDatabase_STATUS) DeepCopyInto(out *RedisEnterpriseDatabase_STATUS) { *out = *in @@ -529,6 +574,11 @@ func (in *RedisEnterpriseDatabase_Spec) DeepCopyInto(out *RedisEnterpriseDatabas (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -595,6 +645,50 @@ func (in *RedisEnterpriseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseOperatorSpec) DeepCopyInto(out *RedisEnterpriseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseOperatorSpec. +func (in *RedisEnterpriseOperatorSpec) DeepCopy() *RedisEnterpriseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterprise_STATUS) DeepCopyInto(out *RedisEnterprise_STATUS) { *out = *in @@ -706,6 +800,11 @@ func (in *RedisEnterprise_Spec) DeepCopyInto(out *RedisEnterprise_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230701/structure.txt b/v2/api/cache/v1api20230701/structure.txt index 3ce34163e95..f4d0408ae21 100644 --- a/v2/api/cache/v1api20230701/structure.txt +++ b/v2/api/cache/v1api20230701/structure.txt @@ -5,13 +5,16 @@ APIVersion: Enum (1 value) └── "2023-07-01" RedisEnterprise: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string │ ├── MinimumTlsVersion: *Enum (3 values) │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sku: *Object (2 properties) │ │ ├── Capacity: *int @@ -73,7 +76,7 @@ RedisEnterprise: Resource └── Zones: string[] RedisEnterpriseDatabase: Resource ├── Owner: RedisEnterprise -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── ClientProtocol: *Enum (2 values) │ │ ├── "Encrypted" @@ -97,6 +100,9 @@ RedisEnterpriseDatabase: Resource │ ├── Modules: Object (2 properties)[] │ │ ├── Args: *string │ │ └── Name: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Persistence: *Object (4 properties) │ │ ├── AofEnabled: *bool diff --git a/v2/api/cache/v1api20230701/zz_generated.deepcopy.go b/v2/api/cache/v1api20230701/zz_generated.deepcopy.go index 1ca7145e436..3cc47b45769 100644 --- a/v2/api/cache/v1api20230701/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230701/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230701 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -345,6 +346,43 @@ func (in *RedisEnterpriseDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopyInto(out *RedisEnterpriseDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseDatabaseOperatorSpec. +func (in *RedisEnterpriseDatabaseOperatorSpec) DeepCopy() *RedisEnterpriseDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterpriseDatabase_STATUS) DeepCopyInto(out *RedisEnterpriseDatabase_STATUS) { *out = *in @@ -459,6 +497,11 @@ func (in *RedisEnterpriseDatabase_Spec) DeepCopyInto(out *RedisEnterpriseDatabas (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -518,6 +561,43 @@ func (in *RedisEnterpriseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisEnterpriseOperatorSpec) DeepCopyInto(out *RedisEnterpriseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisEnterpriseOperatorSpec. +func (in *RedisEnterpriseOperatorSpec) DeepCopy() *RedisEnterpriseOperatorSpec { + if in == nil { + return nil + } + out := new(RedisEnterpriseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisEnterprise_STATUS) DeepCopyInto(out *RedisEnterprise_STATUS) { *out = *in @@ -622,6 +702,11 @@ func (in *RedisEnterprise_Spec) DeepCopyInto(out *RedisEnterprise_Spec) { *out = new(ClusterProperties_MinimumTlsVersion) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisEnterpriseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen.go index 45fdc0b7a59..73c1fdc4ecb 100644 --- a/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *RedisFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisFirewallRule resource func (rule *RedisFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RedisFirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *RedisFirewallRule) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (rule *RedisFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (rule *RedisFirewallRule) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *RedisFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *RedisFirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -244,6 +281,14 @@ func (rule *RedisFirewallRule) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *RedisFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *RedisFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisFirewallRule) @@ -334,6 +379,10 @@ type RedisFirewallRule_Spec struct { // EndIP: highest IP address included in the range EndIP *string `json:"endIP,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -396,6 +445,8 @@ func (rule *RedisFirewallRule_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -474,6 +525,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_From_RedisFirewallRule_Spec // EndIP rule.EndIP = genruntime.ClonePointerToString(source.EndIP) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -500,6 +563,18 @@ func (rule *RedisFirewallRule_Spec) AssignProperties_To_RedisFirewallRule_Spec(d // EndIP destination.EndIP = genruntime.ClonePointerToString(rule.EndIP) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RedisFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RedisFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -732,6 +807,110 @@ func (rule *RedisFirewallRule_STATUS) AssignProperties_To_RedisFirewallRule_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisFirewallRuleOperatorSpec populates our RedisFirewallRuleOperatorSpec from the provided source RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_From_RedisFirewallRuleOperatorSpec(source *storage.RedisFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisFirewallRuleOperatorSpec populates the provided destination RedisFirewallRuleOperatorSpec from our RedisFirewallRuleOperatorSpec +func (operator *RedisFirewallRuleOperatorSpec) AssignProperties_To_RedisFirewallRuleOperatorSpec(destination *storage.RedisFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen_test.go index b231a131c20..2f2a0fecdd6 100644 --- a/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20230801/redis_firewall_rule_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisFirewallRuleOperatorSpec to RedisFirewallRuleOperatorSpec via AssignProperties_To_RedisFirewallRuleOperatorSpec & AssignProperties_From_RedisFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec tests if a specific instance of RedisFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisFirewallRuleOperatorSpec + err := copied.AssignProperties_To_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisFirewallRuleOperatorSpec + err = actual.AssignProperties_From_RedisFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -357,6 +454,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -366,6 +466,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -375,3 +481,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["EndIP"] = gen.PtrOf(gen.AlphaString()) gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20230801/redis_linked_server_types_gen.go b/v2/api/cache/v1api20230801/redis_linked_server_types_gen.go index 3a383856334..e43e516428f 100644 --- a/v2/api/cache/v1api20230801/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20230801/redis_linked_server_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (server *RedisLinkedServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the RedisLinkedServer resource func (server *RedisLinkedServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RedisLinkedServer{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (server *RedisLinkedServer) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (server *RedisLinkedServer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (server *RedisLinkedServer) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return server.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (server *RedisLinkedServer) validateConfigMapDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(server, nil, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (server *RedisLinkedServer) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (server *RedisLinkedServer) validateSecretDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(server, nil, server.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (server *RedisLinkedServer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisLinkedServer) @@ -611,6 +656,10 @@ type RedisLinkedServer_Spec struct { // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -687,6 +736,8 @@ func (server *RedisLinkedServer_Spec) PopulateFromARM(owner genruntime.Arbitrary // no assignment for property "LinkedRedisCacheReference" + // no assignment for property "OperatorSpec" + // Set property "Owner": server.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -775,6 +826,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_From_RedisLinkedServer_Sp server.LinkedRedisCacheReference = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisLinkedServerOperatorSpec + err := operatorSpec.AssignProperties_From_RedisLinkedServerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + server.OperatorSpec = &operatorSpec + } else { + server.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -815,6 +878,18 @@ func (server *RedisLinkedServer_Spec) AssignProperties_To_RedisLinkedServer_Spec destination.LinkedRedisCacheReference = nil } + // OperatorSpec + if server.OperatorSpec != nil { + var operatorSpec storage.RedisLinkedServerOperatorSpec + err := server.OperatorSpec.AssignProperties_To_RedisLinkedServerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisLinkedServerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = server.OriginalVersion() @@ -893,6 +968,110 @@ var redisLinkedServerCreateProperties_ServerRole_Values = map[string]RedisLinked "secondary": RedisLinkedServerCreateProperties_ServerRole_Secondary, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisLinkedServerOperatorSpec populates our RedisLinkedServerOperatorSpec from the provided source RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_From_RedisLinkedServerOperatorSpec(source *storage.RedisLinkedServerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisLinkedServerOperatorSpec populates the provided destination RedisLinkedServerOperatorSpec from our RedisLinkedServerOperatorSpec +func (operator *RedisLinkedServerOperatorSpec) AssignProperties_To_RedisLinkedServerOperatorSpec(destination *storage.RedisLinkedServerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RedisLinkedServerProperties_ServerRole_STATUS string const ( diff --git a/v2/api/cache/v1api20230801/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20230801/redis_linked_server_types_gen_test.go index 98b5124db0e..9b1b114140d 100644 --- a/v2/api/cache/v1api20230801/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20230801/redis_linked_server_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisLinkedServerOperatorSpec to RedisLinkedServerOperatorSpec via AssignProperties_To_RedisLinkedServerOperatorSpec & AssignProperties_From_RedisLinkedServerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec tests if a specific instance of RedisLinkedServerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisLinkedServerOperatorSpec + err := copied.AssignProperties_To_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisLinkedServerOperatorSpec + err = actual.AssignProperties_From_RedisLinkedServerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -250,6 +347,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -259,6 +359,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -269,6 +375,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.OneConstOf(RedisLinkedServerCreateProperties_ServerRole_Primary, RedisLinkedServerCreateProperties_ServerRole_Secondary)) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen.go index 06504825334..4fd44256bf3 100644 --- a/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (schedule *RedisPatchSchedule) Default() { // defaultImpl applies the code generated defaults to the RedisPatchSchedule resource func (schedule *RedisPatchSchedule) defaultImpl() {} +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RedisPatchSchedule{} // InitializeSpec initializes the spec for this resource from the given status @@ -202,7 +225,7 @@ func (schedule *RedisPatchSchedule) ValidateUpdate(old runtime.Object) (admissio // createValidations validates the creation of the resource func (schedule *RedisPatchSchedule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference} + return []func() (admission.Warnings, error){schedule.validateResourceReferences, schedule.validateOwnerReference, schedule.validateSecretDestinations, schedule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -220,7 +243,21 @@ func (schedule *RedisPatchSchedule) updateValidations() []func(old runtime.Objec func(old runtime.Object) (admission.Warnings, error) { return schedule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return schedule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (schedule *RedisPatchSchedule) validateConfigMapDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -237,6 +274,14 @@ func (schedule *RedisPatchSchedule) validateResourceReferences() (admission.Warn return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (schedule *RedisPatchSchedule) validateSecretDestinations() (admission.Warnings, error) { + if schedule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(schedule, nil, schedule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (schedule *RedisPatchSchedule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RedisPatchSchedule) @@ -319,6 +364,10 @@ type RedisPatchScheduleList struct { } type RedisPatchSchedule_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -368,6 +417,8 @@ func (schedule *RedisPatchSchedule_Spec) PopulateFromARM(owner genruntime.Arbitr return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.RedisPatchSchedule_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": schedule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -444,6 +495,18 @@ func (schedule *RedisPatchSchedule_Spec) ConvertSpecTo(destination genruntime.Co // AssignProperties_From_RedisPatchSchedule_Spec populates our RedisPatchSchedule_Spec from the provided source RedisPatchSchedule_Spec func (schedule *RedisPatchSchedule_Spec) AssignProperties_From_RedisPatchSchedule_Spec(source *storage.RedisPatchSchedule_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RedisPatchScheduleOperatorSpec + err := operatorSpec.AssignProperties_From_RedisPatchScheduleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + schedule.OperatorSpec = &operatorSpec + } else { + schedule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -479,6 +542,18 @@ func (schedule *RedisPatchSchedule_Spec) AssignProperties_To_RedisPatchSchedule_ // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if schedule.OperatorSpec != nil { + var operatorSpec storage.RedisPatchScheduleOperatorSpec + err := schedule.OperatorSpec.AssignProperties_To_RedisPatchScheduleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RedisPatchScheduleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = schedule.OriginalVersion() @@ -766,6 +841,110 @@ func (schedule *RedisPatchSchedule_STATUS) AssignProperties_To_RedisPatchSchedul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RedisPatchScheduleOperatorSpec populates our RedisPatchScheduleOperatorSpec from the provided source RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_From_RedisPatchScheduleOperatorSpec(source *storage.RedisPatchScheduleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RedisPatchScheduleOperatorSpec populates the provided destination RedisPatchScheduleOperatorSpec from our RedisPatchScheduleOperatorSpec +func (operator *RedisPatchScheduleOperatorSpec) AssignProperties_To_RedisPatchScheduleOperatorSpec(destination *storage.RedisPatchScheduleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { // +kubebuilder:validation:Required diff --git a/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen_test.go index acf8e094eb3..7e70b16e165 100644 --- a/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20230801/redis_patch_schedule_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RedisPatchScheduleOperatorSpec to RedisPatchScheduleOperatorSpec via AssignProperties_To_RedisPatchScheduleOperatorSpec & AssignProperties_From_RedisPatchScheduleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec tests if a specific instance of RedisPatchScheduleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RedisPatchScheduleOperatorSpec + err := copied.AssignProperties_To_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RedisPatchScheduleOperatorSpec + err = actual.AssignProperties_From_RedisPatchScheduleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -384,6 +481,7 @@ func RedisPatchSchedule_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20230801/redis_types_gen.go b/v2/api/cache/v1api20230801/redis_types_gen.go index 61c959208d0..b117a41647b 100644 --- a/v2/api/cache/v1api20230801/redis_types_gen.go +++ b/v2/api/cache/v1api20230801/redis_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (redis *Redis) defaultAzureName() { // defaultImpl applies the code generated defaults to the Redis resource func (redis *Redis) defaultImpl() { redis.defaultAzureName() } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Redis{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (redis *Redis) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (redis *Redis) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations} + return []func() (admission.Warnings, error){redis.validateResourceReferences, redis.validateOwnerReference, redis.validateSecretDestinations, redis.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (redis *Redis) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return redis.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return redis.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (redis *Redis) validateConfigMapDestinations() (admission.Warnings, error) { + if redis.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(redis, nil, redis.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,17 +286,17 @@ func (redis *Redis) validateSecretDestinations() (admission.Warnings, error) { if redis.Spec.OperatorSpec == nil { return nil, nil } - if redis.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - redis.Spec.OperatorSpec.Secrets.HostName, - redis.Spec.OperatorSpec.Secrets.Port, - redis.Spec.OperatorSpec.Secrets.PrimaryKey, - redis.Spec.OperatorSpec.Secrets.SSLPort, - redis.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if redis.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + redis.Spec.OperatorSpec.Secrets.HostName, + redis.Spec.OperatorSpec.Secrets.Port, + redis.Spec.OperatorSpec.Secrets.PrimaryKey, + redis.Spec.OperatorSpec.Secrets.SSLPort, + redis.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(redis, toValidate, redis.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -3117,6 +3150,12 @@ func (server *RedisLinkedServer_STATUS) AssignProperties_To_RedisLinkedServer_ST // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } @@ -3124,6 +3163,42 @@ type RedisOperatorSpec struct { // AssignProperties_From_RedisOperatorSpec populates our RedisOperatorSpec from the provided source RedisOperatorSpec func (operator *RedisOperatorSpec) AssignProperties_From_RedisOperatorSpec(source *storage.RedisOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret RedisOperatorSecrets @@ -3145,6 +3220,42 @@ func (operator *RedisOperatorSpec) AssignProperties_To_RedisOperatorSpec(destina // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.RedisOperatorSecrets diff --git a/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen.go b/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen.go index c52d810cb17..e4141669b50 100644 --- a/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen.go +++ b/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *RedisFirewallRule) SetConditions(conditions conditions.Conditions) { rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &RedisFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *RedisFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *RedisFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisFirewallRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type RedisFirewallRuleList struct { type RedisFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIP *string `json:"endIP,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIP *string `json:"endIP,omitempty"` + OperatorSpec *RedisFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (rule *RedisFirewallRule_STATUS) ConvertStatusTo(destination genruntime.Con return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20230801.RedisFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&RedisFirewallRule{}, &RedisFirewallRuleList{}) } diff --git a/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen_test.go b/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen_test.go index e89b7416a9f..335dc78aa1d 100644 --- a/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen_test.go +++ b/v2/api/cache/v1api20230801/storage/redis_firewall_rule_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRedisFirewallRule(gens map[string]gopter.Gen gens["Status"] = RedisFirewallRule_STATUSGenerator() } +func Test_RedisFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisFirewallRuleOperatorSpec, RedisFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisFirewallRuleOperatorSpec runs a test to see if a specific instance of RedisFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisFirewallRuleOperatorSpec(subject RedisFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// RedisFirewallRuleOperatorSpecGenerator() +var redisFirewallRuleOperatorSpecGenerator gopter.Gen + +// RedisFirewallRuleOperatorSpecGenerator returns a generator of RedisFirewallRuleOperatorSpec instances for property testing. +func RedisFirewallRuleOperatorSpecGenerator() gopter.Gen { + if redisFirewallRuleOperatorSpecGenerator != nil { + return redisFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRuleOperatorSpec{}), generators) + + return redisFirewallRuleOperatorSpecGenerator +} + func Test_RedisFirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -187,6 +242,9 @@ func RunJSONSerializationTestForRedisFirewallRule_Spec(subject RedisFirewallRule var redisFirewallRule_SpecGenerator gopter.Gen // RedisFirewallRule_SpecGenerator returns a generator of RedisFirewallRule_Spec instances for property testing. +// We first initialize redisFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisFirewallRule_SpecGenerator() gopter.Gen { if redisFirewallRule_SpecGenerator != nil { return redisFirewallRule_SpecGenerator @@ -196,6 +254,12 @@ func RedisFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(generators) + redisFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(RedisFirewallRule_Spec{}), generators) + return redisFirewallRule_SpecGenerator } @@ -206,3 +270,8 @@ func AddIndependentPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]g gens["OriginalVersion"] = gen.AlphaString() gens["StartIP"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen.go b/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen.go index 7719520e4e5..d19cbd781ba 100644 --- a/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen.go +++ b/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (server *RedisLinkedServer) SetConditions(conditions conditions.Conditions) server.Status.Conditions = conditions } +var _ configmaps.Exporter = &RedisLinkedServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *RedisLinkedServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisLinkedServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *RedisLinkedServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisLinkedServer{} // AzureName returns the Azure name of the resource @@ -182,8 +205,9 @@ type RedisLinkedServer_Spec struct { // +kubebuilder:validation:Required // LinkedRedisCacheReference: Fully qualified resourceId of the linked redis cache. - LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + LinkedRedisCacheReference *genruntime.ResourceReference `armReference:"LinkedRedisCacheId" json:"linkedRedisCacheReference,omitempty"` + OperatorSpec *RedisLinkedServerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -214,6 +238,14 @@ func (server *RedisLinkedServer_Spec) ConvertSpecTo(destination genruntime.Conve return destination.ConvertSpecFrom(server) } +// Storage version of v1api20230801.RedisLinkedServerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisLinkedServerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&RedisLinkedServer{}, &RedisLinkedServerList{}) } diff --git a/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen_test.go b/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen_test.go index fb7e6cd0480..7fe045aad6a 100644 --- a/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen_test.go +++ b/v2/api/cache/v1api20230801/storage/redis_linked_server_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRedisLinkedServer(gens map[string]gopter.Gen gens["Status"] = Redis_LinkedServer_STATUSGenerator() } +func Test_RedisLinkedServerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisLinkedServerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisLinkedServerOperatorSpec, RedisLinkedServerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisLinkedServerOperatorSpec runs a test to see if a specific instance of RedisLinkedServerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisLinkedServerOperatorSpec(subject RedisLinkedServerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisLinkedServerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisLinkedServerOperatorSpec instances for property testing - lazily instantiated by +// RedisLinkedServerOperatorSpecGenerator() +var redisLinkedServerOperatorSpecGenerator gopter.Gen + +// RedisLinkedServerOperatorSpecGenerator returns a generator of RedisLinkedServerOperatorSpec instances for property testing. +func RedisLinkedServerOperatorSpecGenerator() gopter.Gen { + if redisLinkedServerOperatorSpecGenerator != nil { + return redisLinkedServerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisLinkedServerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServerOperatorSpec{}), generators) + + return redisLinkedServerOperatorSpecGenerator +} + func Test_RedisLinkedServer_Spec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -122,6 +177,9 @@ func RunJSONSerializationTestForRedisLinkedServer_Spec(subject RedisLinkedServer var redisLinkedServer_SpecGenerator gopter.Gen // RedisLinkedServer_SpecGenerator returns a generator of RedisLinkedServer_Spec instances for property testing. +// We first initialize redisLinkedServer_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RedisLinkedServer_SpecGenerator() gopter.Gen { if redisLinkedServer_SpecGenerator != nil { return redisLinkedServer_SpecGenerator @@ -131,6 +189,12 @@ func RedisLinkedServer_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(generators) + AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(generators) + redisLinkedServer_SpecGenerator = gen.Struct(reflect.TypeOf(RedisLinkedServer_Spec{}), generators) + return redisLinkedServer_SpecGenerator } @@ -142,6 +206,11 @@ func AddIndependentPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]g gens["ServerRole"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRedisLinkedServer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisLinkedServerOperatorSpecGenerator()) +} + func Test_Redis_LinkedServer_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen.go b/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen.go index 0f82baa33da..e04afc87c5e 100644 --- a/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen.go +++ b/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (schedule *RedisPatchSchedule) SetConditions(conditions conditions.Conditio schedule.Status.Conditions = conditions } +var _ configmaps.Exporter = &RedisPatchSchedule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (schedule *RedisPatchSchedule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RedisPatchSchedule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (schedule *RedisPatchSchedule) SecretDestinationExpressions() []*core.DestinationExpression { + if schedule.Spec.OperatorSpec == nil { + return nil + } + return schedule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RedisPatchSchedule{} // AzureName returns the Azure name of the resource (always "default") @@ -140,7 +163,8 @@ type RedisPatchScheduleList struct { // Storage version of v1api20230801.RedisPatchSchedule_Spec type RedisPatchSchedule_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *RedisPatchScheduleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -202,6 +226,14 @@ func (schedule *RedisPatchSchedule_STATUS) ConvertStatusTo(destination genruntim return destination.ConvertStatusFrom(schedule) } +// Storage version of v1api20230801.RedisPatchScheduleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RedisPatchScheduleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230801.ScheduleEntry // Patch schedule entry for a Premium Redis Cache. type ScheduleEntry struct { diff --git a/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen_test.go b/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen_test.go index c40f036044c..73d7ad82a9a 100644 --- a/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen_test.go +++ b/v2/api/cache/v1api20230801/storage/redis_patch_schedule_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRedisPatchSchedule(gens map[string]gopter.Ge gens["Status"] = RedisPatchSchedule_STATUSGenerator() } +func Test_RedisPatchScheduleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RedisPatchScheduleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRedisPatchScheduleOperatorSpec, RedisPatchScheduleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRedisPatchScheduleOperatorSpec runs a test to see if a specific instance of RedisPatchScheduleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRedisPatchScheduleOperatorSpec(subject RedisPatchScheduleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RedisPatchScheduleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RedisPatchScheduleOperatorSpec instances for property testing - lazily instantiated by +// RedisPatchScheduleOperatorSpecGenerator() +var redisPatchScheduleOperatorSpecGenerator gopter.Gen + +// RedisPatchScheduleOperatorSpecGenerator returns a generator of RedisPatchScheduleOperatorSpec instances for property testing. +func RedisPatchScheduleOperatorSpecGenerator() gopter.Gen { + if redisPatchScheduleOperatorSpecGenerator != nil { + return redisPatchScheduleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + redisPatchScheduleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RedisPatchScheduleOperatorSpec{}), generators) + + return redisPatchScheduleOperatorSpecGenerator +} + func Test_RedisPatchSchedule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -228,6 +283,7 @@ func AddIndependentPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string] // AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRedisPatchSchedule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RedisPatchScheduleOperatorSpecGenerator()) gens["ScheduleEntries"] = gen.SliceOf(ScheduleEntryGenerator()) } diff --git a/v2/api/cache/v1api20230801/storage/redis_types_gen.go b/v2/api/cache/v1api20230801/storage/redis_types_gen.go index d63e012b7ba..bd8a9699566 100644 --- a/v2/api/cache/v1api20230801/storage/redis_types_gen.go +++ b/v2/api/cache/v1api20230801/storage/redis_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (redis *Redis) SetConditions(conditions conditions.Conditions) { redis.Status.Conditions = conditions } +var _ configmaps.Exporter = &Redis{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (redis *Redis) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Redis{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (redis *Redis) SecretDestinationExpressions() []*core.DestinationExpression { + if redis.Spec.OperatorSpec == nil { + return nil + } + return redis.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Redis{} // AzureName returns the Azure name of the resource @@ -321,8 +344,10 @@ type RedisLinkedServer_STATUS struct { // Storage version of v1api20230801.RedisOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RedisOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *RedisOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20230801.RedisProperties_RedisConfiguration_STATUS diff --git a/v2/api/cache/v1api20230801/storage/structure.txt b/v2/api/cache/v1api20230801/storage/structure.txt index 851a5103372..148fbe04f84 100644 --- a/v2/api/cache/v1api20230801/storage/structure.txt +++ b/v2/api/cache/v1api20230801/storage/structure.txt @@ -16,8 +16,10 @@ Redis: Resource │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string │ ├── MinimumTlsVersion: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -137,9 +139,13 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: cache/v1api20230801.Redis -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -154,10 +160,14 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: cache/v1api20230801.Redis -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -176,7 +186,11 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: cache/v1api20230801.Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/cache/v1api20230801/storage/zz_generated.deepcopy.go b/v2/api/cache/v1api20230801/storage/zz_generated.deepcopy.go index 2ade55ba64c..cceb9442a7e 100644 --- a/v2/api/cache/v1api20230801/storage/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230801/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -308,6 +309,50 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -370,6 +415,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -510,6 +560,50 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -550,6 +644,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -661,6 +760,17 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -668,6 +778,17 @@ func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -744,6 +865,50 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -803,6 +968,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cache/v1api20230801/structure.txt b/v2/api/cache/v1api20230801/structure.txt index 5855dae5eed..b14fada1a80 100644 --- a/v2/api/cache/v1api20230801/structure.txt +++ b/v2/api/cache/v1api20230801/structure.txt @@ -21,7 +21,9 @@ Redis: Resource │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── HostName: *genruntime.SecretDestination │ │ ├── Port: *genruntime.SecretDestination @@ -167,9 +169,12 @@ Redis: Resource └── Zones: string[] RedisFirewallRule: Resource ├── Owner: Redis -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIP: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIP: *string └── Status: Object (6 properties) @@ -181,10 +186,13 @@ RedisFirewallRule: Resource └── Type: *string RedisLinkedServer: Resource ├── Owner: Redis -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── LinkedRedisCacheLocation: *string │ ├── LinkedRedisCacheReference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ServerRole: *Enum (2 values) │ ├── "Primary" @@ -204,7 +212,10 @@ RedisLinkedServer: Resource └── Type: *string RedisPatchSchedule: Resource ├── Owner: Redis -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── ScheduleEntries: Object (3 properties)[] │ ├── DayOfWeek: *Enum (9 values) diff --git a/v2/api/cache/v1api20230801/zz_generated.deepcopy.go b/v2/api/cache/v1api20230801/zz_generated.deepcopy.go index 62d86ebcae1..1ce2eb460d1 100644 --- a/v2/api/cache/v1api20230801/zz_generated.deepcopy.go +++ b/v2/api/cache/v1api20230801/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230801 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -278,6 +279,43 @@ func (in *RedisFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisFirewallRuleOperatorSpec) DeepCopyInto(out *RedisFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFirewallRuleOperatorSpec. +func (in *RedisFirewallRuleOperatorSpec) DeepCopy() *RedisFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFirewallRule_STATUS) DeepCopyInto(out *RedisFirewallRule_STATUS) { *out = *in @@ -333,6 +371,11 @@ func (in *RedisFirewallRule_Spec) DeepCopyInto(out *RedisFirewallRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -459,6 +502,43 @@ func (in *RedisLinkedServerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisLinkedServerOperatorSpec) DeepCopyInto(out *RedisLinkedServerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLinkedServerOperatorSpec. +func (in *RedisLinkedServerOperatorSpec) DeepCopy() *RedisLinkedServerOperatorSpec { + if in == nil { + return nil + } + out := new(RedisLinkedServerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLinkedServer_STATUS) DeepCopyInto(out *RedisLinkedServer_STATUS) { *out = *in @@ -492,6 +572,11 @@ func (in *RedisLinkedServer_Spec) DeepCopyInto(out *RedisLinkedServer_Spec) { *out = new(genruntime.ResourceReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisLinkedServerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -589,6 +674,28 @@ func (in *RedisOperatorSecrets) DeepCopy() *RedisOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisOperatorSpec) DeepCopyInto(out *RedisOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(RedisOperatorSecrets) @@ -665,6 +772,43 @@ func (in *RedisPatchScheduleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RedisPatchScheduleOperatorSpec) DeepCopyInto(out *RedisPatchScheduleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisPatchScheduleOperatorSpec. +func (in *RedisPatchScheduleOperatorSpec) DeepCopy() *RedisPatchScheduleOperatorSpec { + if in == nil { + return nil + } + out := new(RedisPatchScheduleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_STATUS) DeepCopyInto(out *RedisPatchSchedule_STATUS) { *out = *in @@ -717,6 +861,11 @@ func (in *RedisPatchSchedule_STATUS) DeepCopy() *RedisPatchSchedule_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisPatchSchedule_Spec) DeepCopyInto(out *RedisPatchSchedule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RedisPatchScheduleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cdn/v1api20210601/profile_types_gen.go b/v2/api/cdn/v1api20210601/profile_types_gen.go index d328fb444f5..ab38f8bbf4c 100644 --- a/v2/api/cdn/v1api20210601/profile_types_gen.go +++ b/v2/api/cdn/v1api20210601/profile_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (profile *Profile) defaultAzureName() { // defaultImpl applies the code generated defaults to the Profile resource func (profile *Profile) defaultImpl() { profile.defaultAzureName() } +var _ configmaps.Exporter = &Profile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *Profile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Profile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *Profile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Profile{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (profile *Profile) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (profile *Profile) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference} + return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference, profile.validateSecretDestinations, profile.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (profile *Profile) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return profile.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return profile.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return profile.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (profile *Profile) validateConfigMapDestinations() (admission.Warnings, error) { + if profile.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(profile, nil, profile.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (profile *Profile) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (profile *Profile) validateSecretDestinations() (admission.Warnings, error) { + if profile.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(profile, nil, profile.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (profile *Profile) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Profile) @@ -342,6 +387,10 @@ type Profile_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProfileOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Minimum=16 // OriginResponseTimeoutSeconds: Send and receive timeout on forwarding request to the origin. When timeout is reached, the // request fails and returns. @@ -430,6 +479,8 @@ func (profile *Profile_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe profile.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OriginResponseTimeoutSeconds": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (profile *Profile_Spec) AssignProperties_From_Profile_Spec(source *storage. // Location profile.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProfileOperatorSpec + err := operatorSpec.AssignProperties_From_ProfileOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProfileOperatorSpec() to populate field OperatorSpec") + } + profile.OperatorSpec = &operatorSpec + } else { + profile.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds if source.OriginResponseTimeoutSeconds != nil { originResponseTimeoutSecond := *source.OriginResponseTimeoutSeconds @@ -573,6 +636,18 @@ func (profile *Profile_Spec) AssignProperties_To_Profile_Spec(destination *stora // Location destination.Location = genruntime.ClonePointerToString(profile.Location) + // OperatorSpec + if profile.OperatorSpec != nil { + var operatorSpec storage.ProfileOperatorSpec + err := profile.OperatorSpec.AssignProperties_To_ProfileOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProfileOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds if profile.OriginResponseTimeoutSeconds != nil { originResponseTimeoutSecond := *profile.OriginResponseTimeoutSeconds @@ -999,6 +1074,110 @@ func (profile *Profile_STATUS) AssignProperties_To_Profile_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfileOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProfileOperatorSpec populates our ProfileOperatorSpec from the provided source ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_From_ProfileOperatorSpec(source *storage.ProfileOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProfileOperatorSpec populates the provided destination ProfileOperatorSpec from our ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_To_ProfileOperatorSpec(destination *storage.ProfileOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ProfileProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/cdn/v1api20210601/profile_types_gen_test.go b/v2/api/cdn/v1api20210601/profile_types_gen_test.go index f239a6ae2a4..ec76a61a5c8 100644 --- a/v2/api/cdn/v1api20210601/profile_types_gen_test.go +++ b/v2/api/cdn/v1api20210601/profile_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForProfile(gens map[string]gopter.Gen) { gens["Status"] = Profile_STATUSGenerator() } +func Test_ProfileOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProfileOperatorSpec to ProfileOperatorSpec via AssignProperties_To_ProfileOperatorSpec & AssignProperties_From_ProfileOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProfileOperatorSpec tests if a specific instance of ProfileOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.ProfileOperatorSpec + err := copied.AssignProperties_To_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProfileOperatorSpec + err = actual.AssignProperties_From_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProfileOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfileOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfileOperatorSpec runs a test to see if a specific instance of ProfileOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfileOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfileOperatorSpec instances for property testing - lazily instantiated by +// ProfileOperatorSpecGenerator() +var profileOperatorSpecGenerator gopter.Gen + +// ProfileOperatorSpecGenerator returns a generator of ProfileOperatorSpec instances for property testing. +func ProfileOperatorSpecGenerator() gopter.Gen { + if profileOperatorSpecGenerator != nil { + return profileOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profileOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfileOperatorSpec{}), generators) + + return profileOperatorSpecGenerator +} + func Test_Profile_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -420,6 +517,7 @@ func AddIndependentPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForProfile_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProfileOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen.go b/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen.go index 11345598825..f9c0cf4869e 100644 --- a/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen.go +++ b/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *ProfilesEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the ProfilesEndpoint resource func (endpoint *ProfilesEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &ProfilesEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *ProfilesEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProfilesEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *ProfilesEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ProfilesEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *ProfilesEndpoint) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (endpoint *ProfilesEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *ProfilesEndpoint) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *ProfilesEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *ProfilesEndpoint) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *ProfilesEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *ProfilesEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ProfilesEndpoint) @@ -360,6 +405,10 @@ type ProfilesEndpoint_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProfilesEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // OptimizationType: Specifies what scenario the customer wants this CDN endpoint to optimize for, e.g. Download, Media // services. With this information, CDN can apply scenario driven optimization. OptimizationType *OptimizationType `json:"optimizationType,omitempty"` @@ -643,6 +692,8 @@ func (endpoint *ProfilesEndpoint_Spec) PopulateFromARM(owner genruntime.Arbitrar endpoint.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OptimizationType": // copying flattened property: if typedInput.Properties != nil { @@ -891,6 +942,18 @@ func (endpoint *ProfilesEndpoint_Spec) AssignProperties_From_ProfilesEndpoint_Sp // Location endpoint.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProfilesEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_ProfilesEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProfilesEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // OptimizationType if source.OptimizationType != nil { optimizationType := *source.OptimizationType @@ -1079,6 +1142,18 @@ func (endpoint *ProfilesEndpoint_Spec) AssignProperties_To_ProfilesEndpoint_Spec // Location destination.Location = genruntime.ClonePointerToString(endpoint.Location) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.ProfilesEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_ProfilesEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProfilesEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptimizationType if endpoint.OptimizationType != nil { optimizationType := string(*endpoint.OptimizationType) @@ -4485,6 +4560,110 @@ var optimizationType_STATUS_Values = map[string]OptimizationType_STATUS{ "videoondemandmediastreaming": OptimizationType_STATUS_VideoOnDemandMediaStreaming, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfilesEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProfilesEndpointOperatorSpec populates our ProfilesEndpointOperatorSpec from the provided source ProfilesEndpointOperatorSpec +func (operator *ProfilesEndpointOperatorSpec) AssignProperties_From_ProfilesEndpointOperatorSpec(source *storage.ProfilesEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProfilesEndpointOperatorSpec populates the provided destination ProfilesEndpointOperatorSpec from our ProfilesEndpointOperatorSpec +func (operator *ProfilesEndpointOperatorSpec) AssignProperties_To_ProfilesEndpointOperatorSpec(destination *storage.ProfilesEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Defines how CDN caches requests that include query strings. You can ignore any query strings when caching, bypass // caching to prevent requests that contain query strings from being cached, or cache every request with a unique URL. // +kubebuilder:validation:Enum={"BypassCaching","IgnoreQueryString","NotSet","UseQueryString"} diff --git a/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen_test.go b/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen_test.go index 4429b20beb4..baa1897f5e7 100644 --- a/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen_test.go +++ b/v2/api/cdn/v1api20210601/profiles_endpoint_types_gen_test.go @@ -11475,6 +11475,103 @@ func AddRelatedPropertyGeneratorsForProfilesEndpoint(gens map[string]gopter.Gen) gens["Status"] = ProfilesEndpoint_STATUSGenerator() } +func Test_ProfilesEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProfilesEndpointOperatorSpec to ProfilesEndpointOperatorSpec via AssignProperties_To_ProfilesEndpointOperatorSpec & AssignProperties_From_ProfilesEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProfilesEndpointOperatorSpec, ProfilesEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProfilesEndpointOperatorSpec tests if a specific instance of ProfilesEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProfilesEndpointOperatorSpec(subject ProfilesEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProfilesEndpointOperatorSpec + err := copied.AssignProperties_To_ProfilesEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProfilesEndpointOperatorSpec + err = actual.AssignProperties_From_ProfilesEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProfilesEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfilesEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfilesEndpointOperatorSpec, ProfilesEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfilesEndpointOperatorSpec runs a test to see if a specific instance of ProfilesEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfilesEndpointOperatorSpec(subject ProfilesEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfilesEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfilesEndpointOperatorSpec instances for property testing - lazily instantiated by +// ProfilesEndpointOperatorSpecGenerator() +var profilesEndpointOperatorSpecGenerator gopter.Gen + +// ProfilesEndpointOperatorSpecGenerator returns a generator of ProfilesEndpointOperatorSpec instances for property testing. +func ProfilesEndpointOperatorSpecGenerator() gopter.Gen { + if profilesEndpointOperatorSpecGenerator != nil { + return profilesEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profilesEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfilesEndpointOperatorSpec{}), generators) + + return profilesEndpointOperatorSpecGenerator +} + func Test_ProfilesEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -11777,6 +11874,7 @@ func AddRelatedPropertyGeneratorsForProfilesEndpoint_Spec(gens map[string]gopter gens["DefaultOriginGroup"] = gen.PtrOf(ResourceReferenceGenerator()) gens["DeliveryPolicy"] = gen.PtrOf(EndpointProperties_DeliveryPolicyGenerator()) gens["GeoFilters"] = gen.SliceOf(GeoFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ProfilesEndpointOperatorSpecGenerator()) gens["OriginGroups"] = gen.SliceOf(DeepCreatedOriginGroupGenerator()) gens["Origins"] = gen.SliceOf(DeepCreatedOriginGenerator()) gens["UrlSigningKeys"] = gen.SliceOf(UrlSigningKeyGenerator()) diff --git a/v2/api/cdn/v1api20210601/storage/profile_types_gen.go b/v2/api/cdn/v1api20210601/storage/profile_types_gen.go index fabe663c9df..308c0a541db 100644 --- a/v2/api/cdn/v1api20210601/storage/profile_types_gen.go +++ b/v2/api/cdn/v1api20210601/storage/profile_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cdn/v1api20230501/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (profile *Profile) ConvertTo(hub conversion.Hub) error { return profile.AssignProperties_To_Profile(destination) } +var _ configmaps.Exporter = &Profile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *Profile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Profile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *Profile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Profile{} // AzureName returns the Azure name of the resource @@ -241,10 +264,11 @@ type augmentConversionForProfile interface { type Profile_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginResponseTimeoutSeconds *int `json:"originResponseTimeoutSeconds,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *ProfileOperatorSpec `json:"operatorSpec,omitempty"` + OriginResponseTimeoutSeconds *int `json:"originResponseTimeoutSeconds,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -324,6 +348,18 @@ func (profile *Profile_Spec) AssignProperties_From_Profile_Spec(source *storage. // Location profile.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProfileOperatorSpec + err := operatorSpec.AssignProperties_From_ProfileOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProfileOperatorSpec() to populate field OperatorSpec") + } + profile.OperatorSpec = &operatorSpec + } else { + profile.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds profile.OriginResponseTimeoutSeconds = genruntime.ClonePointerToInt(source.OriginResponseTimeoutSeconds) @@ -397,6 +433,18 @@ func (profile *Profile_Spec) AssignProperties_To_Profile_Spec(destination *stora // Location destination.Location = genruntime.ClonePointerToString(profile.Location) + // OperatorSpec + if profile.OperatorSpec != nil { + var operatorSpec storage.ProfileOperatorSpec + err := profile.OperatorSpec.AssignProperties_To_ProfileOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProfileOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds destination.OriginResponseTimeoutSeconds = genruntime.ClonePointerToInt(profile.OriginResponseTimeoutSeconds) @@ -729,6 +777,136 @@ type augmentConversionForProfile_STATUS interface { AssignPropertiesTo(dst *storage.Profile_STATUS) error } +// Storage version of v1api20210601.ProfileOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfileOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProfileOperatorSpec populates our ProfileOperatorSpec from the provided source ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_From_ProfileOperatorSpec(source *storage.ProfileOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForProfileOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProfileOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ProfileOperatorSpec populates the provided destination ProfileOperatorSpec from our ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_To_ProfileOperatorSpec(destination *storage.ProfileOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForProfileOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForProfileOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210601.Sku // Standard_Verizon = The SKU name for a Standard Verizon CDN profile. // Premium_Verizon = The SKU name for a Premium Verizon @@ -999,6 +1177,11 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination return nil } +type augmentConversionForProfileOperatorSpec interface { + AssignPropertiesFrom(src *storage.ProfileOperatorSpec) error + AssignPropertiesTo(dst *storage.ProfileOperatorSpec) error +} + type augmentConversionForSku interface { AssignPropertiesFrom(src *storage.Sku) error AssignPropertiesTo(dst *storage.Sku) error diff --git a/v2/api/cdn/v1api20210601/storage/profile_types_gen_test.go b/v2/api/cdn/v1api20210601/storage/profile_types_gen_test.go index 07102bfd7c5..4df5bceecb4 100644 --- a/v2/api/cdn/v1api20210601/storage/profile_types_gen_test.go +++ b/v2/api/cdn/v1api20210601/storage/profile_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForProfile(gens map[string]gopter.Gen) { gens["Status"] = Profile_STATUSGenerator() } +func Test_ProfileOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProfileOperatorSpec to ProfileOperatorSpec via AssignProperties_To_ProfileOperatorSpec & AssignProperties_From_ProfileOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProfileOperatorSpec tests if a specific instance of ProfileOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProfileOperatorSpec + err := copied.AssignProperties_To_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProfileOperatorSpec + err = actual.AssignProperties_From_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProfileOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfileOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfileOperatorSpec runs a test to see if a specific instance of ProfileOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfileOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfileOperatorSpec instances for property testing - lazily instantiated by +// ProfileOperatorSpecGenerator() +var profileOperatorSpecGenerator gopter.Gen + +// ProfileOperatorSpecGenerator returns a generator of ProfileOperatorSpec instances for property testing. +func ProfileOperatorSpecGenerator() gopter.Gen { + if profileOperatorSpecGenerator != nil { + return profileOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profileOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfileOperatorSpec{}), generators) + + return profileOperatorSpecGenerator +} + func Test_Profile_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -411,6 +508,7 @@ func AddIndependentPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForProfile_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ProfileOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen.go b/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen.go index 1cf5e1051cd..4bb9441bf64 100644 --- a/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen.go +++ b/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/cdn/v1api20230501/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (endpoint *ProfilesEndpoint) SetConditions(conditions conditions.Conditions endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &ProfilesEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *ProfilesEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ProfilesEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *ProfilesEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ProfilesEndpoint{} // AzureName returns the Azure name of the resource @@ -152,6 +175,7 @@ type ProfilesEndpoint_Spec struct { IsHttpAllowed *bool `json:"isHttpAllowed,omitempty"` IsHttpsAllowed *bool `json:"isHttpsAllowed,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *ProfilesEndpointOperatorSpec `json:"operatorSpec,omitempty"` OptimizationType *string `json:"optimizationType,omitempty"` OriginGroups []DeepCreatedOriginGroup `json:"originGroups,omitempty"` OriginHostHeader *string `json:"originHostHeader,omitempty"` @@ -366,6 +390,14 @@ type GeoFilter_STATUS struct { RelativePath *string `json:"relativePath,omitempty"` } +// Storage version of v1api20210601.ProfilesEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfilesEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210601.ResourceReference // Reference to another resource. type ResourceReference struct { diff --git a/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen_test.go b/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen_test.go index b5e0e34ea33..47df1762fda 100644 --- a/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen_test.go +++ b/v2/api/cdn/v1api20210601/storage/profiles_endpoint_types_gen_test.go @@ -10503,6 +10503,61 @@ func AddRelatedPropertyGeneratorsForProfilesEndpoint(gens map[string]gopter.Gen) gens["Status"] = ProfilesEndpoint_STATUSGenerator() } +func Test_ProfilesEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfilesEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfilesEndpointOperatorSpec, ProfilesEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfilesEndpointOperatorSpec runs a test to see if a specific instance of ProfilesEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfilesEndpointOperatorSpec(subject ProfilesEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfilesEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfilesEndpointOperatorSpec instances for property testing - lazily instantiated by +// ProfilesEndpointOperatorSpecGenerator() +var profilesEndpointOperatorSpecGenerator gopter.Gen + +// ProfilesEndpointOperatorSpecGenerator returns a generator of ProfilesEndpointOperatorSpec instances for property testing. +func ProfilesEndpointOperatorSpecGenerator() gopter.Gen { + if profilesEndpointOperatorSpecGenerator != nil { + return profilesEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profilesEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfilesEndpointOperatorSpec{}), generators) + + return profilesEndpointOperatorSpecGenerator +} + func Test_ProfilesEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -10693,6 +10748,7 @@ func AddRelatedPropertyGeneratorsForProfilesEndpoint_Spec(gens map[string]gopter gens["DefaultOriginGroup"] = gen.PtrOf(ResourceReferenceGenerator()) gens["DeliveryPolicy"] = gen.PtrOf(EndpointProperties_DeliveryPolicyGenerator()) gens["GeoFilters"] = gen.SliceOf(GeoFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ProfilesEndpointOperatorSpecGenerator()) gens["OriginGroups"] = gen.SliceOf(DeepCreatedOriginGroupGenerator()) gens["Origins"] = gen.SliceOf(DeepCreatedOriginGenerator()) gens["UrlSigningKeys"] = gen.SliceOf(UrlSigningKeyGenerator()) diff --git a/v2/api/cdn/v1api20210601/storage/structure.txt b/v2/api/cdn/v1api20210601/storage/structure.txt index 73c7a4e5900..65a54018220 100644 --- a/v2/api/cdn/v1api20210601/storage/structure.txt +++ b/v2/api/cdn/v1api20210601/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2021-06-01" Profile: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginResponseTimeoutSeconds: *int │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference @@ -42,7 +46,7 @@ Profile: Resource └── Type: *string ProfilesEndpoint: Resource ├── Owner: cdn/v1api20210601.Profile -├── Spec: Object (22 properties) +├── Spec: Object (23 properties) │ ├── AzureName: string │ ├── ContentTypesToCompress: string[] │ ├── DefaultOriginGroup: *Object (2 properties) @@ -356,6 +360,10 @@ ProfilesEndpoint: Resource │ ├── IsHttpAllowed: *bool │ ├── IsHttpsAllowed: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OptimizationType: *string │ ├── OriginGroups: Object (6 properties)[] │ │ ├── HealthProbeSettings: *Object (5 properties) @@ -885,6 +893,7 @@ augmentConversionForOriginGroupOverride_STATUS: Interface augmentConversionForPostArgsMatchConditionParameters: Interface augmentConversionForPostArgsMatchConditionParameters_STATUS: Interface augmentConversionForProfile: Interface +augmentConversionForProfileOperatorSpec: Interface augmentConversionForProfile_STATUS: Interface augmentConversionForProfile_Spec: Interface augmentConversionForQueryStringMatchConditionParameters: Interface diff --git a/v2/api/cdn/v1api20210601/storage/zz_generated.deepcopy.go b/v2/api/cdn/v1api20210601/storage/zz_generated.deepcopy.go index b7905c57339..a458e830384 100644 --- a/v2/api/cdn/v1api20210601/storage/zz_generated.deepcopy.go +++ b/v2/api/cdn/v1api20210601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -3934,6 +3935,50 @@ func (in *ProfileList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfileOperatorSpec) DeepCopyInto(out *ProfileOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileOperatorSpec. +func (in *ProfileOperatorSpec) DeepCopy() *ProfileOperatorSpec { + if in == nil { + return nil + } + out := new(ProfileOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile_STATUS) DeepCopyInto(out *Profile_STATUS) { *out = *in @@ -4033,6 +4078,11 @@ func (in *Profile_Spec) DeepCopyInto(out *Profile_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfileOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginResponseTimeoutSeconds != nil { in, out := &in.OriginResponseTimeoutSeconds, &out.OriginResponseTimeoutSeconds *out = new(int) @@ -4133,6 +4183,50 @@ func (in *ProfilesEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfilesEndpointOperatorSpec) DeepCopyInto(out *ProfilesEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfilesEndpointOperatorSpec. +func (in *ProfilesEndpointOperatorSpec) DeepCopy() *ProfilesEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(ProfilesEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProfilesEndpoint_STATUS) DeepCopyInto(out *ProfilesEndpoint_STATUS) { *out = *in @@ -4349,6 +4443,11 @@ func (in *ProfilesEndpoint_Spec) DeepCopyInto(out *ProfilesEndpoint_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfilesEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OptimizationType != nil { in, out := &in.OptimizationType, &out.OptimizationType *out = new(string) diff --git a/v2/api/cdn/v1api20210601/structure.txt b/v2/api/cdn/v1api20210601/structure.txt index 52b87431cbe..68052ec34c4 100644 --- a/v2/api/cdn/v1api20210601/structure.txt +++ b/v2/api/cdn/v1api20210601/structure.txt @@ -5,9 +5,12 @@ APIVersion: Enum (1 value) └── "2021-06-01" Profile: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginResponseTimeoutSeconds: Validated<*int> (1 rule) │ │ └── Rule 0: Minimum: 16 │ ├── Owner: *genruntime.KnownResourceReference @@ -80,7 +83,7 @@ Profile: Resource └── Type: *string ProfilesEndpoint: Resource ├── Owner: Profile -├── Spec: Object (20 properties) +├── Spec: Object (21 properties) │ ├── AzureName: string │ ├── ContentTypesToCompress: string[] │ ├── DefaultOriginGroup: *Object (1 property) @@ -681,6 +684,9 @@ ProfilesEndpoint: Resource │ ├── IsHttpAllowed: *bool │ ├── IsHttpsAllowed: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OptimizationType: *Enum (5 values) │ │ ├── "DynamicSiteAcceleration" │ │ ├── "GeneralMediaStreaming" diff --git a/v2/api/cdn/v1api20210601/zz_generated.deepcopy.go b/v2/api/cdn/v1api20210601/zz_generated.deepcopy.go index 212d6afb253..77240865072 100644 --- a/v2/api/cdn/v1api20210601/zz_generated.deepcopy.go +++ b/v2/api/cdn/v1api20210601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -3255,6 +3256,43 @@ func (in *ProfileList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfileOperatorSpec) DeepCopyInto(out *ProfileOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileOperatorSpec. +func (in *ProfileOperatorSpec) DeepCopy() *ProfileOperatorSpec { + if in == nil { + return nil + } + out := new(ProfileOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile_STATUS) DeepCopyInto(out *Profile_STATUS) { *out = *in @@ -3347,6 +3385,11 @@ func (in *Profile_Spec) DeepCopyInto(out *Profile_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfileOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginResponseTimeoutSeconds != nil { in, out := &in.OriginResponseTimeoutSeconds, &out.OriginResponseTimeoutSeconds *out = new(int) @@ -3440,6 +3483,43 @@ func (in *ProfilesEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfilesEndpointOperatorSpec) DeepCopyInto(out *ProfilesEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfilesEndpointOperatorSpec. +func (in *ProfilesEndpointOperatorSpec) DeepCopy() *ProfilesEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(ProfilesEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProfilesEndpoint_STATUS) DeepCopyInto(out *ProfilesEndpoint_STATUS) { *out = *in @@ -3649,6 +3729,11 @@ func (in *ProfilesEndpoint_Spec) DeepCopyInto(out *ProfilesEndpoint_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfilesEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OptimizationType != nil { in, out := &in.OptimizationType, &out.OptimizationType *out = new(OptimizationType) diff --git a/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen.go b/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen.go index 7b23ce03778..d29feda70b5 100644 --- a/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen.go +++ b/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (domain *AfdCustomDomain) defaultAzureName() { // defaultImpl applies the code generated defaults to the AfdCustomDomain resource func (domain *AfdCustomDomain) defaultImpl() { domain.defaultAzureName() } +var _ configmaps.Exporter = &AfdCustomDomain{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (domain *AfdCustomDomain) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdCustomDomain{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (domain *AfdCustomDomain) SecretDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AfdCustomDomain{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (domain *AfdCustomDomain) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (domain *AfdCustomDomain) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){domain.validateResourceReferences, domain.validateOwnerReference} + return []func() (admission.Warnings, error){domain.validateResourceReferences, domain.validateOwnerReference, domain.validateSecretDestinations, domain.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (domain *AfdCustomDomain) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return domain.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return domain.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return domain.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (domain *AfdCustomDomain) validateConfigMapDestinations() (admission.Warnings, error) { + if domain.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(domain, nil, domain.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (domain *AfdCustomDomain) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (domain *AfdCustomDomain) validateSecretDestinations() (admission.Warnings, error) { + if domain.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(domain, nil, domain.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (domain *AfdCustomDomain) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AfdCustomDomain) @@ -340,6 +385,10 @@ type AfdCustomDomain_Spec struct { // HostName: The host name of the domain. Must be a domain name. HostName *string `json:"hostName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AfdCustomDomainOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -461,6 +510,8 @@ func (domain *AfdCustomDomain_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": domain.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -573,6 +624,18 @@ func (domain *AfdCustomDomain_Spec) AssignProperties_From_AfdCustomDomain_Spec(s // HostName domain.HostName = genruntime.ClonePointerToString(source.HostName) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AfdCustomDomainOperatorSpec + err := operatorSpec.AssignProperties_From_AfdCustomDomainOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AfdCustomDomainOperatorSpec() to populate field OperatorSpec") + } + domain.OperatorSpec = &operatorSpec + } else { + domain.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -635,6 +698,18 @@ func (domain *AfdCustomDomain_Spec) AssignProperties_To_AfdCustomDomain_Spec(des // HostName destination.HostName = genruntime.ClonePointerToString(domain.HostName) + // OperatorSpec + if domain.OperatorSpec != nil { + var operatorSpec storage.AfdCustomDomainOperatorSpec + err := domain.OperatorSpec.AssignProperties_To_AfdCustomDomainOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AfdCustomDomainOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = domain.OriginalVersion() @@ -1244,6 +1319,110 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-05-01") +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdCustomDomainOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AfdCustomDomainOperatorSpec populates our AfdCustomDomainOperatorSpec from the provided source AfdCustomDomainOperatorSpec +func (operator *AfdCustomDomainOperatorSpec) AssignProperties_From_AfdCustomDomainOperatorSpec(source *storage.AfdCustomDomainOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AfdCustomDomainOperatorSpec populates the provided destination AfdCustomDomainOperatorSpec from our AfdCustomDomainOperatorSpec +func (operator *AfdCustomDomainOperatorSpec) AssignProperties_To_AfdCustomDomainOperatorSpec(destination *storage.AfdCustomDomainOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The JSON object that contains the properties to secure a domain. type AFDDomainHttpsParameters struct { // +kubebuilder:validation:Required diff --git a/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen_test.go b/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen_test.go index e9b5127caba..20b3a5023ae 100644 --- a/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/afd_custom_domain_types_gen_test.go @@ -400,6 +400,103 @@ func AddRelatedPropertyGeneratorsForAfdCustomDomain(gens map[string]gopter.Gen) gens["Status"] = AfdCustomDomain_STATUSGenerator() } +func Test_AfdCustomDomainOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AfdCustomDomainOperatorSpec to AfdCustomDomainOperatorSpec via AssignProperties_To_AfdCustomDomainOperatorSpec & AssignProperties_From_AfdCustomDomainOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAfdCustomDomainOperatorSpec, AfdCustomDomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAfdCustomDomainOperatorSpec tests if a specific instance of AfdCustomDomainOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAfdCustomDomainOperatorSpec(subject AfdCustomDomainOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AfdCustomDomainOperatorSpec + err := copied.AssignProperties_To_AfdCustomDomainOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AfdCustomDomainOperatorSpec + err = actual.AssignProperties_From_AfdCustomDomainOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AfdCustomDomainOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdCustomDomainOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdCustomDomainOperatorSpec, AfdCustomDomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdCustomDomainOperatorSpec runs a test to see if a specific instance of AfdCustomDomainOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdCustomDomainOperatorSpec(subject AfdCustomDomainOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdCustomDomainOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdCustomDomainOperatorSpec instances for property testing - lazily instantiated by +// AfdCustomDomainOperatorSpecGenerator() +var afdCustomDomainOperatorSpecGenerator gopter.Gen + +// AfdCustomDomainOperatorSpecGenerator returns a generator of AfdCustomDomainOperatorSpec instances for property testing. +func AfdCustomDomainOperatorSpecGenerator() gopter.Gen { + if afdCustomDomainOperatorSpecGenerator != nil { + return afdCustomDomainOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdCustomDomainOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdCustomDomainOperatorSpec{}), generators) + + return afdCustomDomainOperatorSpecGenerator +} + func Test_AfdCustomDomain_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -668,6 +765,7 @@ func AddIndependentPropertyGeneratorsForAfdCustomDomain_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForAfdCustomDomain_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAfdCustomDomain_Spec(gens map[string]gopter.Gen) { gens["AzureDnsZone"] = gen.PtrOf(ResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdCustomDomainOperatorSpecGenerator()) gens["PreValidatedCustomDomainResourceId"] = gen.PtrOf(ResourceReferenceGenerator()) gens["TlsSettings"] = gen.PtrOf(AFDDomainHttpsParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/afd_endpoint_types_gen.go b/v2/api/cdn/v1api20230501/afd_endpoint_types_gen.go index 1b29a3cf955..8cbbfb4f585 100644 --- a/v2/api/cdn/v1api20230501/afd_endpoint_types_gen.go +++ b/v2/api/cdn/v1api20230501/afd_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *AfdEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the AfdEndpoint resource func (endpoint *AfdEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &AfdEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *AfdEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *AfdEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AfdEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *AfdEndpoint) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (endpoint *AfdEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *AfdEndpoint) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *AfdEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *AfdEndpoint) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *AfdEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *AfdEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AfdEndpoint) @@ -340,6 +385,10 @@ type AfdEndpoint_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AfdEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -438,6 +487,8 @@ func (endpoint *AfdEndpoint_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne endpoint.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -533,6 +584,18 @@ func (endpoint *AfdEndpoint_Spec) AssignProperties_From_AfdEndpoint_Spec(source // Location endpoint.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AfdEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_AfdEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AfdEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -575,6 +638,18 @@ func (endpoint *AfdEndpoint_Spec) AssignProperties_To_AfdEndpoint_Spec(destinati // Location destination.Location = genruntime.ClonePointerToString(endpoint.Location) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.AfdEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_AfdEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AfdEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -1014,6 +1089,110 @@ func (endpoint *AfdEndpoint_STATUS) AssignProperties_To_AfdEndpoint_STATUS(desti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AfdEndpointOperatorSpec populates our AfdEndpointOperatorSpec from the provided source AfdEndpointOperatorSpec +func (operator *AfdEndpointOperatorSpec) AssignProperties_From_AfdEndpointOperatorSpec(source *storage.AfdEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AfdEndpointOperatorSpec populates the provided destination AfdEndpointOperatorSpec from our AfdEndpointOperatorSpec +func (operator *AfdEndpointOperatorSpec) AssignProperties_To_AfdEndpointOperatorSpec(destination *storage.AfdEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AFDEndpointProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/afd_endpoint_types_gen_test.go b/v2/api/cdn/v1api20230501/afd_endpoint_types_gen_test.go index 5fa2d1623cd..073c6085d5b 100644 --- a/v2/api/cdn/v1api20230501/afd_endpoint_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/afd_endpoint_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForAfdEndpoint(gens map[string]gopter.Gen) { gens["Status"] = AfdEndpoint_STATUSGenerator() } +func Test_AfdEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AfdEndpointOperatorSpec to AfdEndpointOperatorSpec via AssignProperties_To_AfdEndpointOperatorSpec & AssignProperties_From_AfdEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAfdEndpointOperatorSpec, AfdEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAfdEndpointOperatorSpec tests if a specific instance of AfdEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAfdEndpointOperatorSpec(subject AfdEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AfdEndpointOperatorSpec + err := copied.AssignProperties_To_AfdEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AfdEndpointOperatorSpec + err = actual.AssignProperties_From_AfdEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AfdEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdEndpointOperatorSpec, AfdEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdEndpointOperatorSpec runs a test to see if a specific instance of AfdEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdEndpointOperatorSpec(subject AfdEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdEndpointOperatorSpec instances for property testing - lazily instantiated by +// AfdEndpointOperatorSpecGenerator() +var afdEndpointOperatorSpecGenerator gopter.Gen + +// AfdEndpointOperatorSpecGenerator returns a generator of AfdEndpointOperatorSpec instances for property testing. +func AfdEndpointOperatorSpecGenerator() gopter.Gen { + if afdEndpointOperatorSpecGenerator != nil { + return afdEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpointOperatorSpec{}), generators) + + return afdEndpointOperatorSpecGenerator +} + func Test_AfdEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -390,6 +487,9 @@ func RunJSONSerializationTestForAfdEndpoint_Spec(subject AfdEndpoint_Spec) strin var afdEndpoint_SpecGenerator gopter.Gen // AfdEndpoint_SpecGenerator returns a generator of AfdEndpoint_Spec instances for property testing. +// We first initialize afdEndpoint_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AfdEndpoint_SpecGenerator() gopter.Gen { if afdEndpoint_SpecGenerator != nil { return afdEndpoint_SpecGenerator @@ -399,6 +499,12 @@ func AfdEndpoint_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(generators) afdEndpoint_SpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpoint_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(generators) + AddRelatedPropertyGeneratorsForAfdEndpoint_Spec(generators) + afdEndpoint_SpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpoint_Spec{}), generators) + return afdEndpoint_SpecGenerator } @@ -416,3 +522,8 @@ func AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(gens map[string]gopter. gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAfdEndpoint_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAfdEndpoint_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AfdEndpointOperatorSpecGenerator()) +} diff --git a/v2/api/cdn/v1api20230501/afd_origin_group_types_gen.go b/v2/api/cdn/v1api20230501/afd_origin_group_types_gen.go index 27663033b86..28676550ab4 100644 --- a/v2/api/cdn/v1api20230501/afd_origin_group_types_gen.go +++ b/v2/api/cdn/v1api20230501/afd_origin_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *AfdOriginGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the AfdOriginGroup resource func (group *AfdOriginGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &AfdOriginGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *AfdOriginGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdOriginGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *AfdOriginGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AfdOriginGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *AfdOriginGroup) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (group *AfdOriginGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *AfdOriginGroup) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *AfdOriginGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *AfdOriginGroup) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *AfdOriginGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *AfdOriginGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AfdOriginGroup) @@ -336,6 +381,10 @@ type AfdOriginGroup_Spec struct { // LoadBalancingSettings: Load balancing settings for a backend pool LoadBalancingSettings *LoadBalancingSettingsParameters `json:"loadBalancingSettings,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AfdOriginGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -444,6 +493,8 @@ func (group *AfdOriginGroup_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -554,6 +605,18 @@ func (group *AfdOriginGroup_Spec) AssignProperties_From_AfdOriginGroup_Spec(sour group.LoadBalancingSettings = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AfdOriginGroupOperatorSpec + err := operatorSpec.AssignProperties_From_AfdOriginGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AfdOriginGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -615,6 +678,18 @@ func (group *AfdOriginGroup_Spec) AssignProperties_To_AfdOriginGroup_Spec(destin destination.LoadBalancingSettings = nil } + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.AfdOriginGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_AfdOriginGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AfdOriginGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -1106,6 +1181,110 @@ func (group *AfdOriginGroup_STATUS) AssignProperties_To_AfdOriginGroup_STATUS(de return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdOriginGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AfdOriginGroupOperatorSpec populates our AfdOriginGroupOperatorSpec from the provided source AfdOriginGroupOperatorSpec +func (operator *AfdOriginGroupOperatorSpec) AssignProperties_From_AfdOriginGroupOperatorSpec(source *storage.AfdOriginGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AfdOriginGroupOperatorSpec populates the provided destination AfdOriginGroupOperatorSpec from our AfdOriginGroupOperatorSpec +func (operator *AfdOriginGroupOperatorSpec) AssignProperties_To_AfdOriginGroupOperatorSpec(destination *storage.AfdOriginGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AFDOriginGroupProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/afd_origin_group_types_gen_test.go b/v2/api/cdn/v1api20230501/afd_origin_group_types_gen_test.go index c00e7d4a7f6..b4eb055373e 100644 --- a/v2/api/cdn/v1api20230501/afd_origin_group_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/afd_origin_group_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForAfdOriginGroup(gens map[string]gopter.Gen) { gens["Status"] = AfdOriginGroup_STATUSGenerator() } +func Test_AfdOriginGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AfdOriginGroupOperatorSpec to AfdOriginGroupOperatorSpec via AssignProperties_To_AfdOriginGroupOperatorSpec & AssignProperties_From_AfdOriginGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAfdOriginGroupOperatorSpec, AfdOriginGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAfdOriginGroupOperatorSpec tests if a specific instance of AfdOriginGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAfdOriginGroupOperatorSpec(subject AfdOriginGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AfdOriginGroupOperatorSpec + err := copied.AssignProperties_To_AfdOriginGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AfdOriginGroupOperatorSpec + err = actual.AssignProperties_From_AfdOriginGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AfdOriginGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdOriginGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdOriginGroupOperatorSpec, AfdOriginGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdOriginGroupOperatorSpec runs a test to see if a specific instance of AfdOriginGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdOriginGroupOperatorSpec(subject AfdOriginGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdOriginGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdOriginGroupOperatorSpec instances for property testing - lazily instantiated by +// AfdOriginGroupOperatorSpecGenerator() +var afdOriginGroupOperatorSpecGenerator gopter.Gen + +// AfdOriginGroupOperatorSpecGenerator returns a generator of AfdOriginGroupOperatorSpec instances for property testing. +func AfdOriginGroupOperatorSpecGenerator() gopter.Gen { + if afdOriginGroupOperatorSpecGenerator != nil { + return afdOriginGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdOriginGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdOriginGroupOperatorSpec{}), generators) + + return afdOriginGroupOperatorSpecGenerator +} + func Test_AfdOriginGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -417,6 +514,7 @@ func AddIndependentPropertyGeneratorsForAfdOriginGroup_Spec(gens map[string]gopt func AddRelatedPropertyGeneratorsForAfdOriginGroup_Spec(gens map[string]gopter.Gen) { gens["HealthProbeSettings"] = gen.PtrOf(HealthProbeParametersGenerator()) gens["LoadBalancingSettings"] = gen.PtrOf(LoadBalancingSettingsParametersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdOriginGroupOperatorSpecGenerator()) } func Test_HealthProbeParameters_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/cdn/v1api20230501/afd_origin_types_gen.go b/v2/api/cdn/v1api20230501/afd_origin_types_gen.go index a0db6b5265f..2401f8f4205 100644 --- a/v2/api/cdn/v1api20230501/afd_origin_types_gen.go +++ b/v2/api/cdn/v1api20230501/afd_origin_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (origin *AfdOrigin) defaultAzureName() { // defaultImpl applies the code generated defaults to the AfdOrigin resource func (origin *AfdOrigin) defaultImpl() { origin.defaultAzureName() } +var _ configmaps.Exporter = &AfdOrigin{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (origin *AfdOrigin) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if origin.Spec.OperatorSpec == nil { + return nil + } + return origin.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdOrigin{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (origin *AfdOrigin) SecretDestinationExpressions() []*core.DestinationExpression { + if origin.Spec.OperatorSpec == nil { + return nil + } + return origin.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AfdOrigin{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (origin *AfdOrigin) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (origin *AfdOrigin) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){origin.validateResourceReferences, origin.validateOwnerReference} + return []func() (admission.Warnings, error){origin.validateResourceReferences, origin.validateOwnerReference, origin.validateSecretDestinations, origin.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (origin *AfdOrigin) updateValidations() []func(old runtime.Object) (admissi func(old runtime.Object) (admission.Warnings, error) { return origin.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return origin.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return origin.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (origin *AfdOrigin) validateConfigMapDestinations() (admission.Warnings, error) { + if origin.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(origin, nil, origin.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (origin *AfdOrigin) validateResourceReferences() (admission.Warnings, error return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (origin *AfdOrigin) validateSecretDestinations() (admission.Warnings, error) { + if origin.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(origin, nil, origin.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (origin *AfdOrigin) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AfdOrigin) @@ -354,6 +399,10 @@ type AfdOrigin_Spec struct { // HttpsPort: The value of the HTTPS port. Must be between 1 and 65535. HttpsPort *int `json:"httpsPort,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AfdOriginOperatorSpec `json:"operatorSpec,omitempty"` + // OriginHostHeader: The host header value sent to the origin with each request. If you leave this blank, the request // hostname determines this value. Azure Front Door origins, such as Web Apps, Blob Storage, and Cloud Services require // this host header value to match the origin hostname by default. This overrides the host header defined at Endpoint @@ -534,6 +583,8 @@ func (origin *AfdOrigin_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRef } } + // no assignment for property "OperatorSpec" + // Set property "OriginHostHeader": // copying flattened property: if typedInput.Properties != nil { @@ -689,6 +740,18 @@ func (origin *AfdOrigin_Spec) AssignProperties_From_AfdOrigin_Spec(source *stora origin.HttpsPort = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AfdOriginOperatorSpec + err := operatorSpec.AssignProperties_From_AfdOriginOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AfdOriginOperatorSpec() to populate field OperatorSpec") + } + origin.OperatorSpec = &operatorSpec + } else { + origin.OperatorSpec = nil + } + // OriginHostHeader origin.OriginHostHeader = genruntime.ClonePointerToString(source.OriginHostHeader) @@ -787,6 +850,18 @@ func (origin *AfdOrigin_Spec) AssignProperties_To_AfdOrigin_Spec(destination *st destination.HttpsPort = nil } + // OperatorSpec + if origin.OperatorSpec != nil { + var operatorSpec storage.AfdOriginOperatorSpec + err := origin.OperatorSpec.AssignProperties_To_AfdOriginOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AfdOriginOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginHostHeader destination.OriginHostHeader = genruntime.ClonePointerToString(origin.OriginHostHeader) @@ -1452,6 +1527,110 @@ func (origin *AfdOrigin_STATUS) AssignProperties_To_AfdOrigin_STATUS(destination return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdOriginOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AfdOriginOperatorSpec populates our AfdOriginOperatorSpec from the provided source AfdOriginOperatorSpec +func (operator *AfdOriginOperatorSpec) AssignProperties_From_AfdOriginOperatorSpec(source *storage.AfdOriginOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AfdOriginOperatorSpec populates the provided destination AfdOriginOperatorSpec from our AfdOriginOperatorSpec +func (operator *AfdOriginOperatorSpec) AssignProperties_To_AfdOriginOperatorSpec(destination *storage.AfdOriginOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AFDOriginProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/afd_origin_types_gen_test.go b/v2/api/cdn/v1api20230501/afd_origin_types_gen_test.go index 1b4d2c66968..d3ef102f210 100644 --- a/v2/api/cdn/v1api20230501/afd_origin_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/afd_origin_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForAfdOrigin(gens map[string]gopter.Gen) { gens["Status"] = AfdOrigin_STATUSGenerator() } +func Test_AfdOriginOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AfdOriginOperatorSpec to AfdOriginOperatorSpec via AssignProperties_To_AfdOriginOperatorSpec & AssignProperties_From_AfdOriginOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAfdOriginOperatorSpec, AfdOriginOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAfdOriginOperatorSpec tests if a specific instance of AfdOriginOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAfdOriginOperatorSpec(subject AfdOriginOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AfdOriginOperatorSpec + err := copied.AssignProperties_To_AfdOriginOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AfdOriginOperatorSpec + err = actual.AssignProperties_From_AfdOriginOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AfdOriginOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdOriginOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdOriginOperatorSpec, AfdOriginOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdOriginOperatorSpec runs a test to see if a specific instance of AfdOriginOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdOriginOperatorSpec(subject AfdOriginOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdOriginOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdOriginOperatorSpec instances for property testing - lazily instantiated by +// AfdOriginOperatorSpecGenerator() +var afdOriginOperatorSpecGenerator gopter.Gen + +// AfdOriginOperatorSpecGenerator returns a generator of AfdOriginOperatorSpec instances for property testing. +func AfdOriginOperatorSpecGenerator() gopter.Gen { + if afdOriginOperatorSpecGenerator != nil { + return afdOriginOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdOriginOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdOriginOperatorSpec{}), generators) + + return afdOriginOperatorSpecGenerator +} + func Test_AfdOrigin_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -426,6 +523,7 @@ func AddIndependentPropertyGeneratorsForAfdOrigin_Spec(gens map[string]gopter.Ge // AddRelatedPropertyGeneratorsForAfdOrigin_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAfdOrigin_Spec(gens map[string]gopter.Gen) { gens["AzureOrigin"] = gen.PtrOf(ResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdOriginOperatorSpecGenerator()) gens["SharedPrivateLinkResource"] = gen.PtrOf(SharedPrivateLinkResourcePropertiesGenerator()) } diff --git a/v2/api/cdn/v1api20230501/profile_types_gen.go b/v2/api/cdn/v1api20230501/profile_types_gen.go index d9191b7e56c..7f463825721 100644 --- a/v2/api/cdn/v1api20230501/profile_types_gen.go +++ b/v2/api/cdn/v1api20230501/profile_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (profile *Profile) defaultAzureName() { // defaultImpl applies the code generated defaults to the Profile resource func (profile *Profile) defaultImpl() { profile.defaultAzureName() } +var _ configmaps.Exporter = &Profile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *Profile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Profile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *Profile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Profile{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (profile *Profile) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (profile *Profile) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference} + return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference, profile.validateSecretDestinations, profile.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (profile *Profile) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return profile.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return profile.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return profile.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (profile *Profile) validateConfigMapDestinations() (admission.Warnings, error) { + if profile.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(profile, nil, profile.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (profile *Profile) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (profile *Profile) validateSecretDestinations() (admission.Warnings, error) { + if profile.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(profile, nil, profile.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (profile *Profile) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Profile) @@ -337,6 +382,10 @@ type Profile_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ProfileOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Minimum=16 // OriginResponseTimeoutSeconds: Send and receive timeout on forwarding request to the origin. When timeout is reached, the // request fails and returns. @@ -446,6 +495,8 @@ func (profile *Profile_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe profile.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OriginResponseTimeoutSeconds": // copying flattened property: if typedInput.Properties != nil { @@ -555,6 +606,18 @@ func (profile *Profile_Spec) AssignProperties_From_Profile_Spec(source *storage. // Location profile.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ProfileOperatorSpec + err := operatorSpec.AssignProperties_From_ProfileOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ProfileOperatorSpec() to populate field OperatorSpec") + } + profile.OperatorSpec = &operatorSpec + } else { + profile.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds if source.OriginResponseTimeoutSeconds != nil { originResponseTimeoutSecond := *source.OriginResponseTimeoutSeconds @@ -613,6 +676,18 @@ func (profile *Profile_Spec) AssignProperties_To_Profile_Spec(destination *stora // Location destination.Location = genruntime.ClonePointerToString(profile.Location) + // OperatorSpec + if profile.OperatorSpec != nil { + var operatorSpec storage.ProfileOperatorSpec + err := profile.OperatorSpec.AssignProperties_To_ProfileOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ProfileOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginResponseTimeoutSeconds if profile.OriginResponseTimeoutSeconds != nil { originResponseTimeoutSecond := *profile.OriginResponseTimeoutSeconds @@ -1463,6 +1538,110 @@ func (identity *ManagedServiceIdentity_STATUS) AssignProperties_To_ManagedServic return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfileOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ProfileOperatorSpec populates our ProfileOperatorSpec from the provided source ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_From_ProfileOperatorSpec(source *storage.ProfileOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ProfileOperatorSpec populates the provided destination ProfileOperatorSpec from our ProfileOperatorSpec +func (operator *ProfileOperatorSpec) AssignProperties_To_ProfileOperatorSpec(destination *storage.ProfileOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ProfileProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/profile_types_gen_test.go b/v2/api/cdn/v1api20230501/profile_types_gen_test.go index 233ab5dbf41..029265c400d 100644 --- a/v2/api/cdn/v1api20230501/profile_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/profile_types_gen_test.go @@ -410,6 +410,103 @@ func AddRelatedPropertyGeneratorsForProfile(gens map[string]gopter.Gen) { gens["Status"] = Profile_STATUSGenerator() } +func Test_ProfileOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ProfileOperatorSpec to ProfileOperatorSpec via AssignProperties_To_ProfileOperatorSpec & AssignProperties_From_ProfileOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForProfileOperatorSpec tests if a specific instance of ProfileOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ProfileOperatorSpec + err := copied.AssignProperties_To_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ProfileOperatorSpec + err = actual.AssignProperties_From_ProfileOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ProfileOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfileOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfileOperatorSpec runs a test to see if a specific instance of ProfileOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfileOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfileOperatorSpec instances for property testing - lazily instantiated by +// ProfileOperatorSpecGenerator() +var profileOperatorSpecGenerator gopter.Gen + +// ProfileOperatorSpecGenerator returns a generator of ProfileOperatorSpec instances for property testing. +func ProfileOperatorSpecGenerator() gopter.Gen { + if profileOperatorSpecGenerator != nil { + return profileOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profileOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfileOperatorSpec{}), generators) + + return profileOperatorSpecGenerator +} + func Test_Profile_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -675,6 +772,7 @@ func AddIndependentPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForProfile_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ProfileOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cdn/v1api20230501/route_types_gen.go b/v2/api/cdn/v1api20230501/route_types_gen.go index e3b2ddafe19..0c29dd45a5e 100644 --- a/v2/api/cdn/v1api20230501/route_types_gen.go +++ b/v2/api/cdn/v1api20230501/route_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (route *Route) defaultAzureName() { // defaultImpl applies the code generated defaults to the Route resource func (route *Route) defaultImpl() { route.defaultAzureName() } +var _ configmaps.Exporter = &Route{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (route *Route) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Route{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (route *Route) SecretDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Route{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (route *Route) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (route *Route) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){route.validateResourceReferences, route.validateOwnerReference} + return []func() (admission.Warnings, error){route.validateResourceReferences, route.validateOwnerReference, route.validateSecretDestinations, route.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (route *Route) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return route.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return route.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return route.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (route *Route) validateConfigMapDestinations() (admission.Warnings, error) { + if route.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(route, nil, route.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (route *Route) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (route *Route) validateSecretDestinations() (admission.Warnings, error) { + if route.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(route, nil, route.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (route *Route) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Route) @@ -350,6 +395,10 @@ type Route_Spec struct { // LinkToDefaultDomain: whether this route will be linked to the default endpoint domain. LinkToDefaultDomain *RouteProperties_LinkToDefaultDomain `json:"linkToDefaultDomain,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RouteOperatorSpec `json:"operatorSpec,omitempty"` + // OriginGroup: A reference to the origin group. OriginGroup *ResourceReference `json:"originGroup,omitempty"` @@ -554,6 +603,8 @@ func (route *Route_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc } } + // no assignment for property "OperatorSpec" + // Set property "OriginGroup": // copying flattened property: if typedInput.Properties != nil { @@ -740,6 +791,18 @@ func (route *Route_Spec) AssignProperties_From_Route_Spec(source *storage.Route_ route.LinkToDefaultDomain = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RouteOperatorSpec + err := operatorSpec.AssignProperties_From_RouteOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RouteOperatorSpec() to populate field OperatorSpec") + } + route.OperatorSpec = &operatorSpec + } else { + route.OperatorSpec = nil + } + // OriginGroup if source.OriginGroup != nil { var originGroup ResourceReference @@ -871,6 +934,18 @@ func (route *Route_Spec) AssignProperties_To_Route_Spec(destination *storage.Rou destination.LinkToDefaultDomain = nil } + // OperatorSpec + if route.OperatorSpec != nil { + var operatorSpec storage.RouteOperatorSpec + err := route.OperatorSpec.AssignProperties_To_RouteOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RouteOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginGroup if route.OriginGroup != nil { var originGroup storage.ResourceReference @@ -2240,6 +2315,110 @@ func (configuration *AfdRouteCacheConfiguration_STATUS) AssignProperties_To_AfdR return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RouteOperatorSpec populates our RouteOperatorSpec from the provided source RouteOperatorSpec +func (operator *RouteOperatorSpec) AssignProperties_From_RouteOperatorSpec(source *storage.RouteOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RouteOperatorSpec populates the provided destination RouteOperatorSpec from our RouteOperatorSpec +func (operator *RouteOperatorSpec) AssignProperties_To_RouteOperatorSpec(destination *storage.RouteOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RouteProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/route_types_gen_test.go b/v2/api/cdn/v1api20230501/route_types_gen_test.go index 6446bf5a0ea..64f26c676ca 100644 --- a/v2/api/cdn/v1api20230501/route_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/route_types_gen_test.go @@ -920,6 +920,102 @@ func AddRelatedPropertyGeneratorsForRoute(gens map[string]gopter.Gen) { gens["Status"] = Route_STATUSGenerator() } +func Test_RouteOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RouteOperatorSpec to RouteOperatorSpec via AssignProperties_To_RouteOperatorSpec & AssignProperties_From_RouteOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRouteOperatorSpec, RouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRouteOperatorSpec tests if a specific instance of RouteOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRouteOperatorSpec(subject RouteOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RouteOperatorSpec + err := copied.AssignProperties_To_RouteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RouteOperatorSpec + err = actual.AssignProperties_From_RouteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RouteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteOperatorSpec, RouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteOperatorSpec runs a test to see if a specific instance of RouteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteOperatorSpec(subject RouteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteOperatorSpec instances for property testing - lazily instantiated by RouteOperatorSpecGenerator() +var routeOperatorSpecGenerator gopter.Gen + +// RouteOperatorSpecGenerator returns a generator of RouteOperatorSpec instances for property testing. +func RouteOperatorSpecGenerator() gopter.Gen { + if routeOperatorSpecGenerator != nil { + return routeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteOperatorSpec{}), generators) + + return routeOperatorSpecGenerator +} + func Test_Route_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1183,6 +1279,7 @@ func AddIndependentPropertyGeneratorsForRoute_Spec(gens map[string]gopter.Gen) { func AddRelatedPropertyGeneratorsForRoute_Spec(gens map[string]gopter.Gen) { gens["CacheConfiguration"] = gen.PtrOf(AfdRouteCacheConfigurationGenerator()) gens["CustomDomains"] = gen.SliceOf(ActivatedResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RouteOperatorSpecGenerator()) gens["OriginGroup"] = gen.PtrOf(ResourceReferenceGenerator()) gens["RuleSets"] = gen.SliceOf(ResourceReferenceGenerator()) } diff --git a/v2/api/cdn/v1api20230501/rule_set_types_gen.go b/v2/api/cdn/v1api20230501/rule_set_types_gen.go index b2db5f2e552..b6af1dfa826 100644 --- a/v2/api/cdn/v1api20230501/rule_set_types_gen.go +++ b/v2/api/cdn/v1api20230501/rule_set_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (ruleSet *RuleSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the RuleSet resource func (ruleSet *RuleSet) defaultImpl() { ruleSet.defaultAzureName() } +var _ configmaps.Exporter = &RuleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (ruleSet *RuleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if ruleSet.Spec.OperatorSpec == nil { + return nil + } + return ruleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RuleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (ruleSet *RuleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if ruleSet.Spec.OperatorSpec == nil { + return nil + } + return ruleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RuleSet{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (ruleSet *RuleSet) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (ruleSet *RuleSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){ruleSet.validateResourceReferences, ruleSet.validateOwnerReference} + return []func() (admission.Warnings, error){ruleSet.validateResourceReferences, ruleSet.validateOwnerReference, ruleSet.validateSecretDestinations, ruleSet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (ruleSet *RuleSet) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return ruleSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return ruleSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return ruleSet.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (ruleSet *RuleSet) validateConfigMapDestinations() (admission.Warnings, error) { + if ruleSet.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(ruleSet, nil, ruleSet.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (ruleSet *RuleSet) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (ruleSet *RuleSet) validateSecretDestinations() (admission.Warnings, error) { + if ruleSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(ruleSet, nil, ruleSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (ruleSet *RuleSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RuleSet) @@ -330,6 +375,10 @@ type RuleSet_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RuleSetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -366,6 +415,8 @@ func (ruleSet *RuleSet_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe // Set property "AzureName": ruleSet.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": ruleSet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -432,6 +483,18 @@ func (ruleSet *RuleSet_Spec) AssignProperties_From_RuleSet_Spec(source *storage. // AzureName ruleSet.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RuleSetOperatorSpec + err := operatorSpec.AssignProperties_From_RuleSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RuleSetOperatorSpec() to populate field OperatorSpec") + } + ruleSet.OperatorSpec = &operatorSpec + } else { + ruleSet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -452,6 +515,18 @@ func (ruleSet *RuleSet_Spec) AssignProperties_To_RuleSet_Spec(destination *stora // AzureName destination.AzureName = ruleSet.AzureName + // OperatorSpec + if ruleSet.OperatorSpec != nil { + var operatorSpec storage.RuleSetOperatorSpec + err := ruleSet.OperatorSpec.AssignProperties_To_RuleSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RuleSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = ruleSet.OriginalVersion() @@ -754,6 +829,110 @@ func (ruleSet *RuleSet_STATUS) AssignProperties_To_RuleSet_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RuleSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RuleSetOperatorSpec populates our RuleSetOperatorSpec from the provided source RuleSetOperatorSpec +func (operator *RuleSetOperatorSpec) AssignProperties_From_RuleSetOperatorSpec(source *storage.RuleSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RuleSetOperatorSpec populates the provided destination RuleSetOperatorSpec from our RuleSetOperatorSpec +func (operator *RuleSetOperatorSpec) AssignProperties_To_RuleSetOperatorSpec(destination *storage.RuleSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RuleSetProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/rule_set_types_gen_test.go b/v2/api/cdn/v1api20230501/rule_set_types_gen_test.go index 476847fc9b5..38b6e83c850 100644 --- a/v2/api/cdn/v1api20230501/rule_set_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/rule_set_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRuleSet(gens map[string]gopter.Gen) { gens["Status"] = RuleSet_STATUSGenerator() } +func Test_RuleSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RuleSetOperatorSpec to RuleSetOperatorSpec via AssignProperties_To_RuleSetOperatorSpec & AssignProperties_From_RuleSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRuleSetOperatorSpec, RuleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRuleSetOperatorSpec tests if a specific instance of RuleSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRuleSetOperatorSpec(subject RuleSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RuleSetOperatorSpec + err := copied.AssignProperties_To_RuleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RuleSetOperatorSpec + err = actual.AssignProperties_From_RuleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RuleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RuleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRuleSetOperatorSpec, RuleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRuleSetOperatorSpec runs a test to see if a specific instance of RuleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRuleSetOperatorSpec(subject RuleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RuleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RuleSetOperatorSpec instances for property testing - lazily instantiated by +// RuleSetOperatorSpecGenerator() +var ruleSetOperatorSpecGenerator gopter.Gen + +// RuleSetOperatorSpecGenerator returns a generator of RuleSetOperatorSpec instances for property testing. +func RuleSetOperatorSpecGenerator() gopter.Gen { + if ruleSetOperatorSpecGenerator != nil { + return ruleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + ruleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RuleSetOperatorSpec{}), generators) + + return ruleSetOperatorSpecGenerator +} + func Test_RuleSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -379,6 +476,9 @@ func RunJSONSerializationTestForRuleSet_Spec(subject RuleSet_Spec) string { var ruleSet_SpecGenerator gopter.Gen // RuleSet_SpecGenerator returns a generator of RuleSet_Spec instances for property testing. +// We first initialize ruleSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RuleSet_SpecGenerator() gopter.Gen { if ruleSet_SpecGenerator != nil { return ruleSet_SpecGenerator @@ -388,6 +488,12 @@ func RuleSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRuleSet_Spec(generators) ruleSet_SpecGenerator = gen.Struct(reflect.TypeOf(RuleSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRuleSet_Spec(generators) + AddRelatedPropertyGeneratorsForRuleSet_Spec(generators) + ruleSet_SpecGenerator = gen.Struct(reflect.TypeOf(RuleSet_Spec{}), generators) + return ruleSet_SpecGenerator } @@ -395,3 +501,8 @@ func RuleSet_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForRuleSet_Spec(gens map[string]gopter.Gen) { gens["AzureName"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForRuleSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRuleSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RuleSetOperatorSpecGenerator()) +} diff --git a/v2/api/cdn/v1api20230501/rule_types_gen.go b/v2/api/cdn/v1api20230501/rule_types_gen.go index 36dce5aca01..9e08672c93a 100644 --- a/v2/api/cdn/v1api20230501/rule_types_gen.go +++ b/v2/api/cdn/v1api20230501/rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *Rule) defaultAzureName() { // defaultImpl applies the code generated defaults to the Rule resource func (rule *Rule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &Rule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *Rule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Rule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *Rule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Rule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *Rule) ValidateUpdate(old runtime.Object) (admission.Warnings, error) // createValidations validates the creation of the resource func (rule *Rule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *Rule) updateValidations() []func(old runtime.Object) (admission.Warn func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *Rule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *Rule) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *Rule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *Rule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Rule) @@ -337,6 +382,10 @@ type Rule_Spec struct { // If not present, defaults to Continue. MatchProcessingBehavior *RuleProperties_MatchProcessingBehavior `json:"matchProcessingBehavior,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RuleOperatorSpec `json:"operatorSpec,omitempty"` + // Order: The order in which the rules are applied for the endpoint. Possible values {0,1,2,3,………}. A rule with a // lesser order will be applied before a rule with a greater order. Rule with order 0 is a special rule. It does not // require any condition and actions listed in it will always be applied. @@ -437,6 +486,8 @@ func (rule *Rule_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, } } + // no assignment for property "OperatorSpec" + // Set property "Order": // copying flattened property: if typedInput.Properties != nil { @@ -552,6 +603,18 @@ func (rule *Rule_Spec) AssignProperties_From_Rule_Spec(source *storage.Rule_Spec rule.MatchProcessingBehavior = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RuleOperatorSpec + err := operatorSpec.AssignProperties_From_RuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Order rule.Order = genruntime.ClonePointerToInt(source.Order) @@ -619,6 +682,18 @@ func (rule *Rule_Spec) AssignProperties_To_Rule_Spec(destination *storage.Rule_S destination.MatchProcessingBehavior = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.RuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_RuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Order destination.Order = genruntime.ClonePointerToInt(rule.Order) @@ -4097,6 +4172,110 @@ func (condition *DeliveryRuleCondition_STATUS) AssignProperties_To_DeliveryRuleC return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RuleOperatorSpec populates our RuleOperatorSpec from the provided source RuleOperatorSpec +func (operator *RuleOperatorSpec) AssignProperties_From_RuleOperatorSpec(source *storage.RuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RuleOperatorSpec populates the provided destination RuleOperatorSpec from our RuleOperatorSpec +func (operator *RuleOperatorSpec) AssignProperties_To_RuleOperatorSpec(destination *storage.RuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type RuleProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/rule_types_gen_test.go b/v2/api/cdn/v1api20230501/rule_types_gen_test.go index 9f6492b310c..8f54750cc49 100644 --- a/v2/api/cdn/v1api20230501/rule_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/rule_types_gen_test.go @@ -11298,6 +11298,102 @@ func AddRelatedPropertyGeneratorsForRule(gens map[string]gopter.Gen) { gens["Status"] = Rule_STATUSGenerator() } +func Test_RuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RuleOperatorSpec to RuleOperatorSpec via AssignProperties_To_RuleOperatorSpec & AssignProperties_From_RuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRuleOperatorSpec, RuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRuleOperatorSpec tests if a specific instance of RuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRuleOperatorSpec(subject RuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RuleOperatorSpec + err := copied.AssignProperties_To_RuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RuleOperatorSpec + err = actual.AssignProperties_From_RuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRuleOperatorSpec, RuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRuleOperatorSpec runs a test to see if a specific instance of RuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRuleOperatorSpec(subject RuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RuleOperatorSpec instances for property testing - lazily instantiated by RuleOperatorSpecGenerator() +var ruleOperatorSpecGenerator gopter.Gen + +// RuleOperatorSpecGenerator returns a generator of RuleOperatorSpec instances for property testing. +func RuleOperatorSpecGenerator() gopter.Gen { + if ruleOperatorSpecGenerator != nil { + return ruleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + ruleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RuleOperatorSpec{}), generators) + + return ruleOperatorSpecGenerator +} + func Test_Rule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -11548,6 +11644,7 @@ func AddIndependentPropertyGeneratorsForRule_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRule_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.SliceOf(DeliveryRuleActionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RuleOperatorSpecGenerator()) gens["RuleConditions"] = gen.SliceOf(DeliveryRuleConditionGenerator()) } diff --git a/v2/api/cdn/v1api20230501/secret_types_gen.go b/v2/api/cdn/v1api20230501/secret_types_gen.go index 78ede758413..eb78963b67f 100644 --- a/v2/api/cdn/v1api20230501/secret_types_gen.go +++ b/v2/api/cdn/v1api20230501/secret_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (secret *Secret) defaultAzureName() { // defaultImpl applies the code generated defaults to the Secret resource func (secret *Secret) defaultImpl() { secret.defaultAzureName() } +var _ configmaps.Exporter = &Secret{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (secret *Secret) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if secret.Spec.OperatorSpec == nil { + return nil + } + return secret.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Secret{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (secret *Secret) SecretDestinationExpressions() []*core.DestinationExpression { + if secret.Spec.OperatorSpec == nil { + return nil + } + return secret.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Secret{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (secret *Secret) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (secret *Secret) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){secret.validateResourceReferences, secret.validateOwnerReference} + return []func() (admission.Warnings, error){secret.validateResourceReferences, secret.validateOwnerReference, secret.validateSecretDestinations, secret.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (secret *Secret) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return secret.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return secret.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return secret.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (secret *Secret) validateConfigMapDestinations() (admission.Warnings, error) { + if secret.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(secret, nil, secret.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (secret *Secret) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(secret) @@ -244,6 +281,14 @@ func (secret *Secret) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (secret *Secret) validateSecretDestinations() (admission.Warnings, error) { + if secret.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(secret, nil, secret.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (secret *Secret) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Secret) @@ -330,6 +375,10 @@ type Secret_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SecretOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -382,6 +431,8 @@ func (secret *Secret_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefere // Set property "AzureName": secret.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": secret.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -462,6 +513,18 @@ func (secret *Secret_Spec) AssignProperties_From_Secret_Spec(source *storage.Sec // AzureName secret.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SecretOperatorSpec + err := operatorSpec.AssignProperties_From_SecretOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SecretOperatorSpec() to populate field OperatorSpec") + } + secret.OperatorSpec = &operatorSpec + } else { + secret.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -494,6 +557,18 @@ func (secret *Secret_Spec) AssignProperties_To_Secret_Spec(destination *storage. // AzureName destination.AzureName = secret.AzureName + // OperatorSpec + if secret.OperatorSpec != nil { + var operatorSpec storage.SecretOperatorSpec + err := secret.OperatorSpec.AssignProperties_To_SecretOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SecretOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = secret.OriginalVersion() @@ -861,6 +936,110 @@ func (secret *Secret_STATUS) AssignProperties_To_Secret_STATUS(destination *stor return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SecretOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SecretOperatorSpec populates our SecretOperatorSpec from the provided source SecretOperatorSpec +func (operator *SecretOperatorSpec) AssignProperties_From_SecretOperatorSpec(source *storage.SecretOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SecretOperatorSpec populates the provided destination SecretOperatorSpec from our SecretOperatorSpec +func (operator *SecretOperatorSpec) AssignProperties_To_SecretOperatorSpec(destination *storage.SecretOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SecretParameters struct { // AzureFirstPartyManagedCertificate: Mutually exclusive with all other properties AzureFirstPartyManagedCertificate *AzureFirstPartyManagedCertificateParameters `json:"azureFirstPartyManagedCertificate,omitempty"` diff --git a/v2/api/cdn/v1api20230501/secret_types_gen_test.go b/v2/api/cdn/v1api20230501/secret_types_gen_test.go index 476dcdc0ef9..eb161d44a26 100644 --- a/v2/api/cdn/v1api20230501/secret_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/secret_types_gen_test.go @@ -842,6 +842,102 @@ func AddRelatedPropertyGeneratorsForSecret(gens map[string]gopter.Gen) { gens["Status"] = Secret_STATUSGenerator() } +func Test_SecretOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SecretOperatorSpec to SecretOperatorSpec via AssignProperties_To_SecretOperatorSpec & AssignProperties_From_SecretOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSecretOperatorSpec, SecretOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSecretOperatorSpec tests if a specific instance of SecretOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSecretOperatorSpec(subject SecretOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SecretOperatorSpec + err := copied.AssignProperties_To_SecretOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SecretOperatorSpec + err = actual.AssignProperties_From_SecretOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SecretOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SecretOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSecretOperatorSpec, SecretOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSecretOperatorSpec runs a test to see if a specific instance of SecretOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSecretOperatorSpec(subject SecretOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SecretOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SecretOperatorSpec instances for property testing - lazily instantiated by SecretOperatorSpecGenerator() +var secretOperatorSpecGenerator gopter.Gen + +// SecretOperatorSpecGenerator returns a generator of SecretOperatorSpec instances for property testing. +func SecretOperatorSpecGenerator() gopter.Gen { + if secretOperatorSpecGenerator != nil { + return secretOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + secretOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SecretOperatorSpec{}), generators) + + return secretOperatorSpecGenerator +} + func Test_SecretParameters_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1325,6 +1421,7 @@ func AddIndependentPropertyGeneratorsForSecret_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForSecret_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSecret_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SecretOperatorSpecGenerator()) gens["Parameters"] = gen.PtrOf(SecretParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/security_policy_types_gen.go b/v2/api/cdn/v1api20230501/security_policy_types_gen.go index c099c205214..48dac948f0d 100644 --- a/v2/api/cdn/v1api20230501/security_policy_types_gen.go +++ b/v2/api/cdn/v1api20230501/security_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (policy *SecurityPolicy) defaultAzureName() { // defaultImpl applies the code generated defaults to the SecurityPolicy resource func (policy *SecurityPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &SecurityPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *SecurityPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SecurityPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *SecurityPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SecurityPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (policy *SecurityPolicy) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (policy *SecurityPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (policy *SecurityPolicy) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *SecurityPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (policy *SecurityPolicy) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *SecurityPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *SecurityPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SecurityPolicy) @@ -330,6 +375,10 @@ type SecurityPolicy_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SecurityPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -382,6 +431,8 @@ func (policy *SecurityPolicy_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": policy.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -462,6 +513,18 @@ func (policy *SecurityPolicy_Spec) AssignProperties_From_SecurityPolicy_Spec(sou // AzureName policy.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SecurityPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_SecurityPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SecurityPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -494,6 +557,18 @@ func (policy *SecurityPolicy_Spec) AssignProperties_To_SecurityPolicy_Spec(desti // AzureName destination.AzureName = policy.AzureName + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.SecurityPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_SecurityPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SecurityPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -861,6 +936,110 @@ func (policy *SecurityPolicy_STATUS) AssignProperties_To_SecurityPolicy_STATUS(d return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SecurityPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SecurityPolicyOperatorSpec populates our SecurityPolicyOperatorSpec from the provided source SecurityPolicyOperatorSpec +func (operator *SecurityPolicyOperatorSpec) AssignProperties_From_SecurityPolicyOperatorSpec(source *storage.SecurityPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SecurityPolicyOperatorSpec populates the provided destination SecurityPolicyOperatorSpec from our SecurityPolicyOperatorSpec +func (operator *SecurityPolicyOperatorSpec) AssignProperties_To_SecurityPolicyOperatorSpec(destination *storage.SecurityPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SecurityPolicyProperties_DeploymentStatus_STATUS string const ( diff --git a/v2/api/cdn/v1api20230501/security_policy_types_gen_test.go b/v2/api/cdn/v1api20230501/security_policy_types_gen_test.go index 335a0392ba5..65b919f77f2 100644 --- a/v2/api/cdn/v1api20230501/security_policy_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/security_policy_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForSecurityPolicy(gens map[string]gopter.Gen) { gens["Status"] = SecurityPolicy_STATUSGenerator() } +func Test_SecurityPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SecurityPolicyOperatorSpec to SecurityPolicyOperatorSpec via AssignProperties_To_SecurityPolicyOperatorSpec & AssignProperties_From_SecurityPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSecurityPolicyOperatorSpec, SecurityPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSecurityPolicyOperatorSpec tests if a specific instance of SecurityPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSecurityPolicyOperatorSpec(subject SecurityPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SecurityPolicyOperatorSpec + err := copied.AssignProperties_To_SecurityPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SecurityPolicyOperatorSpec + err = actual.AssignProperties_From_SecurityPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SecurityPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SecurityPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSecurityPolicyOperatorSpec, SecurityPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSecurityPolicyOperatorSpec runs a test to see if a specific instance of SecurityPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSecurityPolicyOperatorSpec(subject SecurityPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SecurityPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SecurityPolicyOperatorSpec instances for property testing - lazily instantiated by +// SecurityPolicyOperatorSpecGenerator() +var securityPolicyOperatorSpecGenerator gopter.Gen + +// SecurityPolicyOperatorSpecGenerator returns a generator of SecurityPolicyOperatorSpec instances for property testing. +func SecurityPolicyOperatorSpecGenerator() gopter.Gen { + if securityPolicyOperatorSpecGenerator != nil { + return securityPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + securityPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SecurityPolicyOperatorSpec{}), generators) + + return securityPolicyOperatorSpecGenerator +} + func Test_SecurityPolicyPropertiesParameters_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1102,5 +1199,6 @@ func AddIndependentPropertyGeneratorsForSecurityPolicy_Spec(gens map[string]gopt // AddRelatedPropertyGeneratorsForSecurityPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSecurityPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SecurityPolicyOperatorSpecGenerator()) gens["Parameters"] = gen.PtrOf(SecurityPolicyPropertiesParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen.go b/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen.go index bb80d630aae..daecfbdc5e4 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (domain *AfdCustomDomain) SetConditions(conditions conditions.Conditions) { domain.Status.Conditions = conditions } +var _ configmaps.Exporter = &AfdCustomDomain{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (domain *AfdCustomDomain) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdCustomDomain{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (domain *AfdCustomDomain) SecretDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AfdCustomDomain{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type AfdCustomDomain_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ExtendedProperties map[string]string `json:"extendedProperties,omitempty"` - HostName *string `json:"hostName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ExtendedProperties map[string]string `json:"extendedProperties,omitempty"` + HostName *string `json:"hostName,omitempty"` + OperatorSpec *AfdCustomDomainOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -225,6 +249,14 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-05-01") +// Storage version of v1api20230501.AfdCustomDomainOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdCustomDomainOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.AFDDomainHttpsParameters // The JSON object that contains the properties to secure a domain. type AFDDomainHttpsParameters struct { diff --git a/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen_test.go index e2973aed3cd..8a5dbce9956 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/afd_custom_domain_types_gen_test.go @@ -230,6 +230,61 @@ func AddRelatedPropertyGeneratorsForAfdCustomDomain(gens map[string]gopter.Gen) gens["Status"] = AfdCustomDomain_STATUSGenerator() } +func Test_AfdCustomDomainOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdCustomDomainOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdCustomDomainOperatorSpec, AfdCustomDomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdCustomDomainOperatorSpec runs a test to see if a specific instance of AfdCustomDomainOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdCustomDomainOperatorSpec(subject AfdCustomDomainOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdCustomDomainOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdCustomDomainOperatorSpec instances for property testing - lazily instantiated by +// AfdCustomDomainOperatorSpecGenerator() +var afdCustomDomainOperatorSpecGenerator gopter.Gen + +// AfdCustomDomainOperatorSpecGenerator returns a generator of AfdCustomDomainOperatorSpec instances for property testing. +func AfdCustomDomainOperatorSpecGenerator() gopter.Gen { + if afdCustomDomainOperatorSpecGenerator != nil { + return afdCustomDomainOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdCustomDomainOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdCustomDomainOperatorSpec{}), generators) + + return afdCustomDomainOperatorSpecGenerator +} + func Test_AfdCustomDomain_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -397,6 +452,7 @@ func AddIndependentPropertyGeneratorsForAfdCustomDomain_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForAfdCustomDomain_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAfdCustomDomain_Spec(gens map[string]gopter.Gen) { gens["AzureDnsZone"] = gen.PtrOf(ResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdCustomDomainOperatorSpecGenerator()) gens["PreValidatedCustomDomainResourceId"] = gen.PtrOf(ResourceReferenceGenerator()) gens["TlsSettings"] = gen.PtrOf(AFDDomainHttpsParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen.go b/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen.go index e8b85841912..39385ec8898 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *AfdEndpoint) SetConditions(conditions conditions.Conditions) { endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &AfdEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *AfdEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *AfdEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AfdEndpoint{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type AfdEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnabledState *string `json:"enabledState,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnabledState *string `json:"enabledState,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *AfdEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -216,6 +240,14 @@ func (endpoint *AfdEndpoint_STATUS) ConvertStatusTo(destination genruntime.Conve return destination.ConvertStatusFrom(endpoint) } +// Storage version of v1api20230501.AfdEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&AfdEndpoint{}, &AfdEndpointList{}) } diff --git a/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen_test.go index e00dc28c24c..3b0319434cd 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/afd_endpoint_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForAfdEndpoint(gens map[string]gopter.Gen) { gens["Status"] = AfdEndpoint_STATUSGenerator() } +func Test_AfdEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdEndpointOperatorSpec, AfdEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdEndpointOperatorSpec runs a test to see if a specific instance of AfdEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdEndpointOperatorSpec(subject AfdEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdEndpointOperatorSpec instances for property testing - lazily instantiated by +// AfdEndpointOperatorSpecGenerator() +var afdEndpointOperatorSpecGenerator gopter.Gen + +// AfdEndpointOperatorSpecGenerator returns a generator of AfdEndpointOperatorSpec instances for property testing. +func AfdEndpointOperatorSpecGenerator() gopter.Gen { + if afdEndpointOperatorSpecGenerator != nil { + return afdEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpointOperatorSpec{}), generators) + + return afdEndpointOperatorSpecGenerator +} + func Test_AfdEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -207,6 +262,9 @@ func RunJSONSerializationTestForAfdEndpoint_Spec(subject AfdEndpoint_Spec) strin var afdEndpoint_SpecGenerator gopter.Gen // AfdEndpoint_SpecGenerator returns a generator of AfdEndpoint_Spec instances for property testing. +// We first initialize afdEndpoint_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func AfdEndpoint_SpecGenerator() gopter.Gen { if afdEndpoint_SpecGenerator != nil { return afdEndpoint_SpecGenerator @@ -216,6 +274,12 @@ func AfdEndpoint_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(generators) afdEndpoint_SpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpoint_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(generators) + AddRelatedPropertyGeneratorsForAfdEndpoint_Spec(generators) + afdEndpoint_SpecGenerator = gen.Struct(reflect.TypeOf(AfdEndpoint_Spec{}), generators) + return afdEndpoint_SpecGenerator } @@ -230,3 +294,8 @@ func AddIndependentPropertyGeneratorsForAfdEndpoint_Spec(gens map[string]gopter. gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForAfdEndpoint_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAfdEndpoint_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AfdEndpointOperatorSpecGenerator()) +} diff --git a/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen.go b/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen.go index efe9bd1e910..b8646cdade2 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *AfdOriginGroup) SetConditions(conditions conditions.Conditions) { group.Status.Conditions = conditions } +var _ configmaps.Exporter = &AfdOriginGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *AfdOriginGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdOriginGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *AfdOriginGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AfdOriginGroup{} // AzureName returns the Azure name of the resource @@ -145,6 +168,7 @@ type AfdOriginGroup_Spec struct { AzureName string `json:"azureName,omitempty"` HealthProbeSettings *HealthProbeParameters `json:"healthProbeSettings,omitempty"` LoadBalancingSettings *LoadBalancingSettingsParameters `json:"loadBalancingSettings,omitempty"` + OperatorSpec *AfdOriginGroupOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -214,6 +238,14 @@ func (group *AfdOriginGroup_STATUS) ConvertStatusTo(destination genruntime.Conve return destination.ConvertStatusFrom(group) } +// Storage version of v1api20230501.AfdOriginGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdOriginGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.HealthProbeParameters // The JSON object that contains the properties to send health probes to origin. type HealthProbeParameters struct { diff --git a/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen_test.go index 875c19ea92f..846afcaef83 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/afd_origin_group_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForAfdOriginGroup(gens map[string]gopter.Gen) { gens["Status"] = AfdOriginGroup_STATUSGenerator() } +func Test_AfdOriginGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdOriginGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdOriginGroupOperatorSpec, AfdOriginGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdOriginGroupOperatorSpec runs a test to see if a specific instance of AfdOriginGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdOriginGroupOperatorSpec(subject AfdOriginGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdOriginGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdOriginGroupOperatorSpec instances for property testing - lazily instantiated by +// AfdOriginGroupOperatorSpecGenerator() +var afdOriginGroupOperatorSpecGenerator gopter.Gen + +// AfdOriginGroupOperatorSpecGenerator returns a generator of AfdOriginGroupOperatorSpec instances for property testing. +func AfdOriginGroupOperatorSpecGenerator() gopter.Gen { + if afdOriginGroupOperatorSpecGenerator != nil { + return afdOriginGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdOriginGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdOriginGroupOperatorSpec{}), generators) + + return afdOriginGroupOperatorSpecGenerator +} + func Test_AfdOriginGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -239,6 +294,7 @@ func AddIndependentPropertyGeneratorsForAfdOriginGroup_Spec(gens map[string]gopt func AddRelatedPropertyGeneratorsForAfdOriginGroup_Spec(gens map[string]gopter.Gen) { gens["HealthProbeSettings"] = gen.PtrOf(HealthProbeParametersGenerator()) gens["LoadBalancingSettings"] = gen.PtrOf(LoadBalancingSettingsParametersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdOriginGroupOperatorSpecGenerator()) } func Test_HealthProbeParameters_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen.go b/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen.go index 661019759b0..226a3395e2d 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (origin *AfdOrigin) SetConditions(conditions conditions.Conditions) { origin.Status.Conditions = conditions } +var _ configmaps.Exporter = &AfdOrigin{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (origin *AfdOrigin) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if origin.Spec.OperatorSpec == nil { + return nil + } + return origin.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AfdOrigin{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (origin *AfdOrigin) SecretDestinationExpressions() []*core.DestinationExpression { + if origin.Spec.OperatorSpec == nil { + return nil + } + return origin.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AfdOrigin{} // AzureName returns the Azure name of the resource @@ -142,15 +165,16 @@ type AfdOriginList struct { type AfdOrigin_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - AzureOrigin *ResourceReference `json:"azureOrigin,omitempty"` - EnabledState *string `json:"enabledState,omitempty"` - EnforceCertificateNameCheck *bool `json:"enforceCertificateNameCheck,omitempty"` - HostName *string `json:"hostName,omitempty"` - HttpPort *int `json:"httpPort,omitempty"` - HttpsPort *int `json:"httpsPort,omitempty"` - OriginHostHeader *string `json:"originHostHeader,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + AzureOrigin *ResourceReference `json:"azureOrigin,omitempty"` + EnabledState *string `json:"enabledState,omitempty"` + EnforceCertificateNameCheck *bool `json:"enforceCertificateNameCheck,omitempty"` + HostName *string `json:"hostName,omitempty"` + HttpPort *int `json:"httpPort,omitempty"` + HttpsPort *int `json:"httpsPort,omitempty"` + OperatorSpec *AfdOriginOperatorSpec `json:"operatorSpec,omitempty"` + OriginHostHeader *string `json:"originHostHeader,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -226,6 +250,14 @@ func (origin *AfdOrigin_STATUS) ConvertStatusTo(destination genruntime.Convertib return destination.ConvertStatusFrom(origin) } +// Storage version of v1api20230501.AfdOriginOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AfdOriginOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.SharedPrivateLinkResourceProperties // Describes the properties of an existing Shared Private Link Resource to use when connecting to a private origin. type SharedPrivateLinkResourceProperties struct { diff --git a/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen_test.go index 18a6d62c19e..801ec9eace3 100644 --- a/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/afd_origin_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForAfdOrigin(gens map[string]gopter.Gen) { gens["Status"] = AfdOrigin_STATUSGenerator() } +func Test_AfdOriginOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AfdOriginOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAfdOriginOperatorSpec, AfdOriginOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAfdOriginOperatorSpec runs a test to see if a specific instance of AfdOriginOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAfdOriginOperatorSpec(subject AfdOriginOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AfdOriginOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AfdOriginOperatorSpec instances for property testing - lazily instantiated by +// AfdOriginOperatorSpecGenerator() +var afdOriginOperatorSpecGenerator gopter.Gen + +// AfdOriginOperatorSpecGenerator returns a generator of AfdOriginOperatorSpec instances for property testing. +func AfdOriginOperatorSpecGenerator() gopter.Gen { + if afdOriginOperatorSpecGenerator != nil { + return afdOriginOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + afdOriginOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AfdOriginOperatorSpec{}), generators) + + return afdOriginOperatorSpecGenerator +} + func Test_AfdOrigin_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -248,6 +303,7 @@ func AddIndependentPropertyGeneratorsForAfdOrigin_Spec(gens map[string]gopter.Ge // AddRelatedPropertyGeneratorsForAfdOrigin_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAfdOrigin_Spec(gens map[string]gopter.Gen) { gens["AzureOrigin"] = gen.PtrOf(ResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AfdOriginOperatorSpecGenerator()) gens["SharedPrivateLinkResource"] = gen.PtrOf(SharedPrivateLinkResourcePropertiesGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/profile_types_gen.go b/v2/api/cdn/v1api20230501/storage/profile_types_gen.go index cf73f829a55..9d458ec4ea5 100644 --- a/v2/api/cdn/v1api20230501/storage/profile_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/profile_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (profile *Profile) SetConditions(conditions conditions.Conditions) { profile.Status.Conditions = conditions } +var _ configmaps.Exporter = &Profile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *Profile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Profile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *Profile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Profile{} // AzureName returns the Azure name of the resource @@ -145,6 +168,7 @@ type Profile_Spec struct { AzureName string `json:"azureName,omitempty"` Identity *ManagedServiceIdentity `json:"identity,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *ProfileOperatorSpec `json:"operatorSpec,omitempty"` OriginResponseTimeoutSeconds *int `json:"originResponseTimeoutSeconds,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` @@ -237,6 +261,14 @@ type ManagedServiceIdentity_STATUS struct { UserAssignedIdentities map[string]UserAssignedIdentity_STATUS `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20230501.ProfileOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ProfileOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.Sku // Standard_Verizon = The SKU name for a Standard Verizon CDN profile. // Premium_Verizon = The SKU name for a Premium Verizon diff --git a/v2/api/cdn/v1api20230501/storage/profile_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/profile_types_gen_test.go index 7631c382060..ddbc3d68c21 100644 --- a/v2/api/cdn/v1api20230501/storage/profile_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/profile_types_gen_test.go @@ -232,6 +232,61 @@ func AddRelatedPropertyGeneratorsForProfile(gens map[string]gopter.Gen) { gens["Status"] = Profile_STATUSGenerator() } +func Test_ProfileOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ProfileOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForProfileOperatorSpec, ProfileOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForProfileOperatorSpec runs a test to see if a specific instance of ProfileOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForProfileOperatorSpec(subject ProfileOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ProfileOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ProfileOperatorSpec instances for property testing - lazily instantiated by +// ProfileOperatorSpecGenerator() +var profileOperatorSpecGenerator gopter.Gen + +// ProfileOperatorSpecGenerator returns a generator of ProfileOperatorSpec instances for property testing. +func ProfileOperatorSpecGenerator() gopter.Gen { + if profileOperatorSpecGenerator != nil { + return profileOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + profileOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ProfileOperatorSpec{}), generators) + + return profileOperatorSpecGenerator +} + func Test_Profile_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -400,6 +455,7 @@ func AddIndependentPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForProfile_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForProfile_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ProfileOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/route_types_gen.go b/v2/api/cdn/v1api20230501/storage/route_types_gen.go index 58534a2598f..f550d443aa5 100644 --- a/v2/api/cdn/v1api20230501/storage/route_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/route_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (route *Route) SetConditions(conditions conditions.Conditions) { route.Status.Conditions = conditions } +var _ configmaps.Exporter = &Route{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (route *Route) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Route{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (route *Route) SecretDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Route{} // AzureName returns the Azure name of the resource @@ -149,6 +172,7 @@ type Route_Spec struct { ForwardingProtocol *string `json:"forwardingProtocol,omitempty"` HttpsRedirect *string `json:"httpsRedirect,omitempty"` LinkToDefaultDomain *string `json:"linkToDefaultDomain,omitempty"` + OperatorSpec *RouteOperatorSpec `json:"operatorSpec,omitempty"` OriginGroup *ResourceReference `json:"originGroup,omitempty"` OriginPath *string `json:"originPath,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` @@ -262,6 +286,14 @@ type AfdRouteCacheConfiguration_STATUS struct { QueryStringCachingBehavior *string `json:"queryStringCachingBehavior,omitempty"` } +// Storage version of v1api20230501.RouteOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.CompressionSettings // settings for compression. type CompressionSettings struct { diff --git a/v2/api/cdn/v1api20230501/storage/route_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/route_types_gen_test.go index 6dd7d7fe65b..ee5bd8379d8 100644 --- a/v2/api/cdn/v1api20230501/storage/route_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/route_types_gen_test.go @@ -471,6 +471,60 @@ func AddRelatedPropertyGeneratorsForRoute(gens map[string]gopter.Gen) { gens["Status"] = Route_STATUSGenerator() } +func Test_RouteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteOperatorSpec, RouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteOperatorSpec runs a test to see if a specific instance of RouteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteOperatorSpec(subject RouteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteOperatorSpec instances for property testing - lazily instantiated by RouteOperatorSpecGenerator() +var routeOperatorSpecGenerator gopter.Gen + +// RouteOperatorSpecGenerator returns a generator of RouteOperatorSpec instances for property testing. +func RouteOperatorSpecGenerator() gopter.Gen { + if routeOperatorSpecGenerator != nil { + return routeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteOperatorSpec{}), generators) + + return routeOperatorSpecGenerator +} + func Test_Route_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -642,6 +696,7 @@ func AddIndependentPropertyGeneratorsForRoute_Spec(gens map[string]gopter.Gen) { func AddRelatedPropertyGeneratorsForRoute_Spec(gens map[string]gopter.Gen) { gens["CacheConfiguration"] = gen.PtrOf(AfdRouteCacheConfigurationGenerator()) gens["CustomDomains"] = gen.SliceOf(ActivatedResourceReferenceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RouteOperatorSpecGenerator()) gens["OriginGroup"] = gen.PtrOf(ResourceReferenceGenerator()) gens["RuleSets"] = gen.SliceOf(ResourceReferenceGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/rule_set_types_gen.go b/v2/api/cdn/v1api20230501/storage/rule_set_types_gen.go index d551173d2be..c696dcbb4c5 100644 --- a/v2/api/cdn/v1api20230501/storage/rule_set_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/rule_set_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (ruleSet *RuleSet) SetConditions(conditions conditions.Conditions) { ruleSet.Status.Conditions = conditions } +var _ configmaps.Exporter = &RuleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (ruleSet *RuleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if ruleSet.Spec.OperatorSpec == nil { + return nil + } + return ruleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RuleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (ruleSet *RuleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if ruleSet.Spec.OperatorSpec == nil { + return nil + } + return ruleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RuleSet{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type RuleSetList struct { type RuleSet_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *RuleSetOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (ruleSet *RuleSet_STATUS) ConvertStatusTo(destination genruntime.Convertibl return destination.ConvertStatusFrom(ruleSet) } +// Storage version of v1api20230501.RuleSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RuleSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&RuleSet{}, &RuleSetList{}) } diff --git a/v2/api/cdn/v1api20230501/storage/rule_set_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/rule_set_types_gen_test.go index 129db1ce0a5..2d306a9633f 100644 --- a/v2/api/cdn/v1api20230501/storage/rule_set_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/rule_set_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRuleSet(gens map[string]gopter.Gen) { gens["Status"] = RuleSet_STATUSGenerator() } +func Test_RuleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RuleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRuleSetOperatorSpec, RuleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRuleSetOperatorSpec runs a test to see if a specific instance of RuleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRuleSetOperatorSpec(subject RuleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RuleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RuleSetOperatorSpec instances for property testing - lazily instantiated by +// RuleSetOperatorSpecGenerator() +var ruleSetOperatorSpecGenerator gopter.Gen + +// RuleSetOperatorSpecGenerator returns a generator of RuleSetOperatorSpec instances for property testing. +func RuleSetOperatorSpecGenerator() gopter.Gen { + if ruleSetOperatorSpecGenerator != nil { + return ruleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + ruleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RuleSetOperatorSpec{}), generators) + + return ruleSetOperatorSpecGenerator +} + func Test_RuleSet_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -200,6 +255,9 @@ func RunJSONSerializationTestForRuleSet_Spec(subject RuleSet_Spec) string { var ruleSet_SpecGenerator gopter.Gen // RuleSet_SpecGenerator returns a generator of RuleSet_Spec instances for property testing. +// We first initialize ruleSet_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RuleSet_SpecGenerator() gopter.Gen { if ruleSet_SpecGenerator != nil { return ruleSet_SpecGenerator @@ -209,6 +267,12 @@ func RuleSet_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRuleSet_Spec(generators) ruleSet_SpecGenerator = gen.Struct(reflect.TypeOf(RuleSet_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRuleSet_Spec(generators) + AddRelatedPropertyGeneratorsForRuleSet_Spec(generators) + ruleSet_SpecGenerator = gen.Struct(reflect.TypeOf(RuleSet_Spec{}), generators) + return ruleSet_SpecGenerator } @@ -217,3 +281,8 @@ func AddIndependentPropertyGeneratorsForRuleSet_Spec(gens map[string]gopter.Gen) gens["AzureName"] = gen.AlphaString() gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForRuleSet_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRuleSet_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RuleSetOperatorSpecGenerator()) +} diff --git a/v2/api/cdn/v1api20230501/storage/rule_types_gen.go b/v2/api/cdn/v1api20230501/storage/rule_types_gen.go index cdba8582fd7..2962887f7f9 100644 --- a/v2/api/cdn/v1api20230501/storage/rule_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *Rule) SetConditions(conditions conditions.Conditions) { rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &Rule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *Rule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Rule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *Rule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Rule{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type Rule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - MatchProcessingBehavior *string `json:"matchProcessingBehavior,omitempty"` - Order *int `json:"order,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + MatchProcessingBehavior *string `json:"matchProcessingBehavior,omitempty"` + OperatorSpec *RuleOperatorSpec `json:"operatorSpec,omitempty"` + Order *int `json:"order,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -295,6 +319,14 @@ type DeliveryRuleCondition_STATUS struct { UrlPath *DeliveryRuleUrlPathCondition_STATUS `json:"urlPath,omitempty"` } +// Storage version of v1api20230501.RuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.DeliveryRuleCacheExpirationAction type DeliveryRuleCacheExpirationAction struct { Name *string `json:"name,omitempty"` diff --git a/v2/api/cdn/v1api20230501/storage/rule_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/rule_types_gen_test.go index c31b51a2436..e972f07ca14 100644 --- a/v2/api/cdn/v1api20230501/storage/rule_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/rule_types_gen_test.go @@ -6918,6 +6918,60 @@ func AddRelatedPropertyGeneratorsForRule(gens map[string]gopter.Gen) { gens["Status"] = Rule_STATUSGenerator() } +func Test_RuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRuleOperatorSpec, RuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRuleOperatorSpec runs a test to see if a specific instance of RuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRuleOperatorSpec(subject RuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RuleOperatorSpec instances for property testing - lazily instantiated by RuleOperatorSpecGenerator() +var ruleOperatorSpecGenerator gopter.Gen + +// RuleOperatorSpecGenerator returns a generator of RuleOperatorSpec instances for property testing. +func RuleOperatorSpecGenerator() gopter.Gen { + if ruleOperatorSpecGenerator != nil { + return ruleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + ruleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RuleOperatorSpec{}), generators) + + return ruleOperatorSpecGenerator +} + func Test_Rule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -7076,6 +7130,7 @@ func AddIndependentPropertyGeneratorsForRule_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForRule_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.SliceOf(DeliveryRuleActionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RuleOperatorSpecGenerator()) gens["RuleConditions"] = gen.SliceOf(DeliveryRuleConditionGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/secret_types_gen.go b/v2/api/cdn/v1api20230501/storage/secret_types_gen.go index 73130628720..f9314f8bdf7 100644 --- a/v2/api/cdn/v1api20230501/storage/secret_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/secret_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (secret *Secret) SetConditions(conditions conditions.Conditions) { secret.Status.Conditions = conditions } +var _ configmaps.Exporter = &Secret{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (secret *Secret) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if secret.Spec.OperatorSpec == nil { + return nil + } + return secret.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Secret{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (secret *Secret) SecretDestinationExpressions() []*core.DestinationExpression { + if secret.Spec.OperatorSpec == nil { + return nil + } + return secret.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Secret{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type SecretList struct { type Secret_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *SecretOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -208,6 +232,14 @@ func (secret *Secret_STATUS) ConvertStatusTo(destination genruntime.ConvertibleS return destination.ConvertStatusFrom(secret) } +// Storage version of v1api20230501.SecretOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SecretOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.SecretParameters type SecretParameters struct { AzureFirstPartyManagedCertificate *AzureFirstPartyManagedCertificateParameters `json:"azureFirstPartyManagedCertificate,omitempty"` diff --git a/v2/api/cdn/v1api20230501/storage/secret_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/secret_types_gen_test.go index 922f4439cfc..3581a4715d2 100644 --- a/v2/api/cdn/v1api20230501/storage/secret_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/secret_types_gen_test.go @@ -504,6 +504,60 @@ func AddRelatedPropertyGeneratorsForSecret(gens map[string]gopter.Gen) { gens["Status"] = Secret_STATUSGenerator() } +func Test_SecretOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SecretOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSecretOperatorSpec, SecretOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSecretOperatorSpec runs a test to see if a specific instance of SecretOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSecretOperatorSpec(subject SecretOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SecretOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SecretOperatorSpec instances for property testing - lazily instantiated by SecretOperatorSpecGenerator() +var secretOperatorSpecGenerator gopter.Gen + +// SecretOperatorSpecGenerator returns a generator of SecretOperatorSpec instances for property testing. +func SecretOperatorSpecGenerator() gopter.Gen { + if secretOperatorSpecGenerator != nil { + return secretOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + secretOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SecretOperatorSpec{}), generators) + + return secretOperatorSpecGenerator +} + func Test_SecretParameters_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -811,6 +865,7 @@ func AddIndependentPropertyGeneratorsForSecret_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForSecret_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSecret_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SecretOperatorSpecGenerator()) gens["Parameters"] = gen.PtrOf(SecretParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/security_policy_types_gen.go b/v2/api/cdn/v1api20230501/storage/security_policy_types_gen.go index ab81e994404..a6608faeefd 100644 --- a/v2/api/cdn/v1api20230501/storage/security_policy_types_gen.go +++ b/v2/api/cdn/v1api20230501/storage/security_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *SecurityPolicy) SetConditions(conditions conditions.Conditions) { policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &SecurityPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *SecurityPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SecurityPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *SecurityPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SecurityPolicy{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type SecurityPolicyList struct { type SecurityPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *SecurityPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -208,6 +232,14 @@ func (policy *SecurityPolicy_STATUS) ConvertStatusTo(destination genruntime.Conv return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20230501.SecurityPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SecurityPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.SecurityPolicyPropertiesParameters type SecurityPolicyPropertiesParameters struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` diff --git a/v2/api/cdn/v1api20230501/storage/security_policy_types_gen_test.go b/v2/api/cdn/v1api20230501/storage/security_policy_types_gen_test.go index f78923c724e..bb07f496046 100644 --- a/v2/api/cdn/v1api20230501/storage/security_policy_types_gen_test.go +++ b/v2/api/cdn/v1api20230501/storage/security_policy_types_gen_test.go @@ -139,6 +139,61 @@ func AddRelatedPropertyGeneratorsForSecurityPolicy(gens map[string]gopter.Gen) { gens["Status"] = SecurityPolicy_STATUSGenerator() } +func Test_SecurityPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SecurityPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSecurityPolicyOperatorSpec, SecurityPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSecurityPolicyOperatorSpec runs a test to see if a specific instance of SecurityPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSecurityPolicyOperatorSpec(subject SecurityPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SecurityPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SecurityPolicyOperatorSpec instances for property testing - lazily instantiated by +// SecurityPolicyOperatorSpecGenerator() +var securityPolicyOperatorSpecGenerator gopter.Gen + +// SecurityPolicyOperatorSpecGenerator returns a generator of SecurityPolicyOperatorSpec instances for property testing. +func SecurityPolicyOperatorSpecGenerator() gopter.Gen { + if securityPolicyOperatorSpecGenerator != nil { + return securityPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + securityPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SecurityPolicyOperatorSpec{}), generators) + + return securityPolicyOperatorSpecGenerator +} + func Test_SecurityPolicyPropertiesParameters_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -733,5 +788,6 @@ func AddIndependentPropertyGeneratorsForSecurityPolicy_Spec(gens map[string]gopt // AddRelatedPropertyGeneratorsForSecurityPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSecurityPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SecurityPolicyOperatorSpecGenerator()) gens["Parameters"] = gen.PtrOf(SecurityPolicyPropertiesParametersGenerator()) } diff --git a/v2/api/cdn/v1api20230501/storage/structure.txt b/v2/api/cdn/v1api20230501/storage/structure.txt index cb5a999a549..d4cad6ea819 100644 --- a/v2/api/cdn/v1api20230501/storage/structure.txt +++ b/v2/api/cdn/v1api20230501/storage/structure.txt @@ -5,13 +5,17 @@ APIVersion: Enum (1 value) └── "2023-05-01" AfdCustomDomain: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureDnsZone: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── AzureName: string │ ├── ExtendedProperties: map[string]string │ ├── HostName: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PreValidatedCustomDomainResourceId: *Object (2 properties) @@ -64,11 +68,15 @@ AfdCustomDomain: Resource └── ValidationToken: *string AfdEndpoint: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AutoGeneratedDomainNameLabelScope: *string │ ├── AzureName: string │ ├── EnabledState: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -97,7 +105,7 @@ AfdEndpoint: Resource └── Type: *string AfdOrigin: Resource ├── Owner: cdn/v1api20230501.AfdOriginGroup -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AzureName: string │ ├── AzureOrigin: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -107,6 +115,10 @@ AfdOrigin: Resource │ ├── HostName: *string │ ├── HttpPort: *int │ ├── HttpsPort: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginHostHeader: *string │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference @@ -161,7 +173,7 @@ AfdOrigin: Resource └── Weight: *int AfdOriginGroup: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── HealthProbeSettings: *Object (5 properties) │ │ ├── ProbeIntervalInSeconds: *int @@ -174,6 +186,10 @@ AfdOriginGroup: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── SampleSize: *int │ │ └── SuccessfulSamplesRequired: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -211,7 +227,7 @@ AfdOriginGroup: Resource └── Type: *string Profile: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Identity: *Object (3 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -220,6 +236,10 @@ Profile: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginResponseTimeoutSeconds: *int │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference @@ -264,7 +284,7 @@ Profile: Resource └── Type: *string Route: Resource ├── Owner: cdn/v1api20230501.AfdEndpoint -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AzureName: string │ ├── CacheConfiguration: *Object (4 properties) │ │ ├── CompressionSettings: *Object (3 properties) @@ -281,6 +301,10 @@ Route: Resource │ ├── ForwardingProtocol: *string │ ├── HttpsRedirect: *string │ ├── LinkToDefaultDomain: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginGroup: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference @@ -336,7 +360,7 @@ Route: Resource └── Type: *string Rule: Resource ├── Owner: cdn/v1api20230501.RuleSet -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── Actions: Object (10 properties)[] │ │ ├── CacheExpiration: *Object (3 properties) │ │ │ ├── Name: *string @@ -436,6 +460,10 @@ Rule: Resource │ │ └── PropertyBag: genruntime.PropertyBag │ ├── AzureName: string │ ├── MatchProcessingBehavior: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Order: *int │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference @@ -948,8 +976,12 @@ Rule: Resource └── Type: *string RuleSet: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -972,8 +1004,12 @@ RuleSet: Resource └── Type: *string Secret: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Parameters: *Object (5 properties) @@ -1061,8 +1097,12 @@ Secret: Resource └── Type: *string SecurityPolicy: Resource ├── Owner: cdn/v1api20230501.Profile -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Parameters: *Object (2 properties) diff --git a/v2/api/cdn/v1api20230501/storage/zz_generated.deepcopy.go b/v2/api/cdn/v1api20230501/storage/zz_generated.deepcopy.go index 06a9f3c818e..5c0d01bf49f 100644 --- a/v2/api/cdn/v1api20230501/storage/zz_generated.deepcopy.go +++ b/v2/api/cdn/v1api20230501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -229,6 +230,50 @@ func (in *AfdCustomDomainList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdCustomDomainOperatorSpec) DeepCopyInto(out *AfdCustomDomainOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdCustomDomainOperatorSpec. +func (in *AfdCustomDomainOperatorSpec) DeepCopy() *AfdCustomDomainOperatorSpec { + if in == nil { + return nil + } + out := new(AfdCustomDomainOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdCustomDomain_STATUS) DeepCopyInto(out *AfdCustomDomain_STATUS) { *out = *in @@ -350,6 +395,11 @@ func (in *AfdCustomDomain_Spec) DeepCopyInto(out *AfdCustomDomain_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdCustomDomainOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -443,6 +493,50 @@ func (in *AfdEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdEndpointOperatorSpec) DeepCopyInto(out *AfdEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdEndpointOperatorSpec. +func (in *AfdEndpointOperatorSpec) DeepCopy() *AfdEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(AfdEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdEndpoint_STATUS) DeepCopyInto(out *AfdEndpoint_STATUS) { *out = *in @@ -552,6 +646,11 @@ func (in *AfdEndpoint_Spec) DeepCopyInto(out *AfdEndpoint_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -669,6 +768,50 @@ func (in *AfdOriginGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdOriginGroupOperatorSpec) DeepCopyInto(out *AfdOriginGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdOriginGroupOperatorSpec. +func (in *AfdOriginGroupOperatorSpec) DeepCopy() *AfdOriginGroupOperatorSpec { + if in == nil { + return nil + } + out := new(AfdOriginGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdOriginGroup_STATUS) DeepCopyInto(out *AfdOriginGroup_STATUS) { *out = *in @@ -766,6 +909,11 @@ func (in *AfdOriginGroup_Spec) DeepCopyInto(out *AfdOriginGroup_Spec) { *out = new(LoadBalancingSettingsParameters) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdOriginGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -832,6 +980,50 @@ func (in *AfdOriginList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdOriginOperatorSpec) DeepCopyInto(out *AfdOriginOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdOriginOperatorSpec. +func (in *AfdOriginOperatorSpec) DeepCopy() *AfdOriginOperatorSpec { + if in == nil { + return nil + } + out := new(AfdOriginOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdOrigin_STATUS) DeepCopyInto(out *AfdOrigin_STATUS) { *out = *in @@ -979,6 +1171,11 @@ func (in *AfdOrigin_Spec) DeepCopyInto(out *AfdOrigin_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdOriginOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginHostHeader != nil { in, out := &in.OriginHostHeader, &out.OriginHostHeader *out = new(string) @@ -4771,6 +4968,50 @@ func (in *ProfileList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfileOperatorSpec) DeepCopyInto(out *ProfileOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileOperatorSpec. +func (in *ProfileOperatorSpec) DeepCopy() *ProfileOperatorSpec { + if in == nil { + return nil + } + out := new(ProfileOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile_STATUS) DeepCopyInto(out *Profile_STATUS) { *out = *in @@ -4887,6 +5128,11 @@ func (in *Profile_Spec) DeepCopyInto(out *Profile_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfileOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginResponseTimeoutSeconds != nil { in, out := &in.OriginResponseTimeoutSeconds, &out.OriginResponseTimeoutSeconds *out = new(int) @@ -5783,6 +6029,50 @@ func (in *RouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteOperatorSpec) DeepCopyInto(out *RouteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteOperatorSpec. +func (in *RouteOperatorSpec) DeepCopy() *RouteOperatorSpec { + if in == nil { + return nil + } + out := new(RouteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Route_STATUS) DeepCopyInto(out *Route_STATUS) { *out = *in @@ -5941,6 +6231,11 @@ func (in *Route_Spec) DeepCopyInto(out *Route_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginGroup != nil { in, out := &in.OriginGroup, &out.OriginGroup *out = new(ResourceReference) @@ -6051,6 +6346,50 @@ func (in *RuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleOperatorSpec) DeepCopyInto(out *RuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleOperatorSpec. +func (in *RuleOperatorSpec) DeepCopy() *RuleOperatorSpec { + if in == nil { + return nil + } + out := new(RuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet) DeepCopyInto(out *RuleSet) { *out = *in @@ -6110,6 +6449,50 @@ func (in *RuleSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleSetOperatorSpec) DeepCopyInto(out *RuleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleSetOperatorSpec. +func (in *RuleSetOperatorSpec) DeepCopy() *RuleSetOperatorSpec { + if in == nil { + return nil + } + out := new(RuleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet_STATUS) DeepCopyInto(out *RuleSet_STATUS) { *out = *in @@ -6177,6 +6560,11 @@ func (in *RuleSet_STATUS) DeepCopy() *RuleSet_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet_Spec) DeepCopyInto(out *RuleSet_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RuleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6304,6 +6692,11 @@ func (in *Rule_Spec) DeepCopyInto(out *Rule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Order != nil { in, out := &in.Order, &out.Order *out = new(int) @@ -6399,6 +6792,50 @@ func (in *SecretList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretOperatorSpec) DeepCopyInto(out *SecretOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretOperatorSpec. +func (in *SecretOperatorSpec) DeepCopy() *SecretOperatorSpec { + if in == nil { + return nil + } + out := new(SecretOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretParameters) DeepCopyInto(out *SecretParameters) { *out = *in @@ -6555,6 +6992,11 @@ func (in *Secret_STATUS) DeepCopy() *Secret_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret_Spec) DeepCopyInto(out *Secret_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SecretOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6643,6 +7085,50 @@ func (in *SecurityPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityPolicyOperatorSpec) DeepCopyInto(out *SecurityPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityPolicyOperatorSpec. +func (in *SecurityPolicyOperatorSpec) DeepCopy() *SecurityPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(SecurityPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityPolicyPropertiesParameters) DeepCopyInto(out *SecurityPolicyPropertiesParameters) { *out = *in @@ -6915,6 +7401,11 @@ func (in *SecurityPolicy_STATUS) DeepCopy() *SecurityPolicy_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityPolicy_Spec) DeepCopyInto(out *SecurityPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SecurityPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/cdn/v1api20230501/structure.txt b/v2/api/cdn/v1api20230501/structure.txt index d28ca9c1ec5..bd886e6bd85 100644 --- a/v2/api/cdn/v1api20230501/structure.txt +++ b/v2/api/cdn/v1api20230501/structure.txt @@ -5,12 +5,15 @@ APIVersion: Enum (1 value) └── "2023-05-01" AfdCustomDomain: Resource ├── Owner: Profile -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureDnsZone: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference │ ├── AzureName: string │ ├── ExtendedProperties: map[string]string │ ├── HostName: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PreValidatedCustomDomainResourceId: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -87,7 +90,7 @@ AfdCustomDomain: Resource └── ValidationToken: *string AfdEndpoint: Resource ├── Owner: Profile -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AutoGeneratedDomainNameLabelScope: *Enum (4 values) │ │ ├── "NoReuse" │ │ ├── "ResourceGroupReuse" @@ -98,6 +101,9 @@ AfdEndpoint: Resource │ │ ├── "Disabled" │ │ └── "Enabled" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (13 properties) @@ -145,7 +151,7 @@ AfdEndpoint: Resource └── Type: *string AfdOrigin: Resource ├── Owner: AfdOriginGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AzureName: string │ ├── AzureOrigin: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -160,6 +166,9 @@ AfdOrigin: Resource │ ├── HttpsPort: Validated<*int> (2 rules) │ │ ├── Rule 0: Maximum: 65535 │ │ └── Rule 1: Minimum: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginHostHeader: *string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: Validated<*int> (2 rules) @@ -238,7 +247,7 @@ AfdOrigin: Resource └── Weight: *int AfdOriginGroup: Resource ├── Owner: Profile -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── HealthProbeSettings: *Object (4 properties) │ │ ├── ProbeIntervalInSeconds: Validated<*int> (2 rules) @@ -257,6 +266,9 @@ AfdOriginGroup: Resource │ │ ├── AdditionalLatencyInMilliseconds: *int │ │ ├── SampleSize: *int │ │ └── SuccessfulSamplesRequired: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── SessionAffinityState: *Enum (2 values) │ │ ├── "Disabled" @@ -317,7 +329,7 @@ AfdOriginGroup: Resource └── Type: *string Profile: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Identity: *Object (2 properties) │ │ ├── Type: *Enum (4 values) @@ -328,6 +340,9 @@ Profile: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginResponseTimeoutSeconds: Validated<*int> (1 rule) │ │ └── Rule 0: Minimum: 16 │ ├── Owner: *genruntime.KnownResourceReference @@ -417,7 +432,7 @@ Profile: Resource └── Type: *string Route: Resource ├── Owner: AfdEndpoint -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── CacheConfiguration: *Object (3 properties) │ │ ├── CompressionSettings: *Object (2 properties) @@ -444,6 +459,9 @@ Route: Resource │ ├── LinkToDefaultDomain: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginGroup: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference │ ├── OriginPath: *string @@ -522,7 +540,7 @@ Route: Resource └── Type: *string Rule: Resource ├── Owner: RuleSet -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Actions: Object (9 properties)[] │ │ ├── CacheExpiration: *Object (2 properties) │ │ │ ├── Name: *Enum (1 value) @@ -655,6 +673,9 @@ Rule: Resource │ ├── MatchProcessingBehavior: *Enum (2 values) │ │ ├── "Continue" │ │ └── "Stop" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Order: *int │ ├── Owner: *genruntime.KnownResourceReference │ └── RuleConditions: Object (19 properties)[] @@ -1729,8 +1750,11 @@ Rule: Resource └── Type: *string RuleSet: Resource ├── Owner: Profile -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (8 properties) ├── Conditions: conditions.Condition[] @@ -1766,8 +1790,11 @@ RuleSet: Resource └── Type: *string Secret: Resource ├── Owner: Profile -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Parameters: *Object (4 properties) │ ├── AzureFirstPartyManagedCertificate: *Object (2 properties) @@ -1861,8 +1888,11 @@ Secret: Resource └── Type: *string SecurityPolicy: Resource ├── Owner: Profile -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Parameters: *Object (1 property) │ └── WebApplicationFirewall: *Object (3 properties) diff --git a/v2/api/cdn/v1api20230501/zz_generated.deepcopy.go b/v2/api/cdn/v1api20230501/zz_generated.deepcopy.go index 240f93a13ab..840796736cb 100644 --- a/v2/api/cdn/v1api20230501/zz_generated.deepcopy.go +++ b/v2/api/cdn/v1api20230501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -194,6 +195,43 @@ func (in *AfdCustomDomainList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdCustomDomainOperatorSpec) DeepCopyInto(out *AfdCustomDomainOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdCustomDomainOperatorSpec. +func (in *AfdCustomDomainOperatorSpec) DeepCopy() *AfdCustomDomainOperatorSpec { + if in == nil { + return nil + } + out := new(AfdCustomDomainOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdCustomDomain_STATUS) DeepCopyInto(out *AfdCustomDomain_STATUS) { *out = *in @@ -308,6 +346,11 @@ func (in *AfdCustomDomain_Spec) DeepCopyInto(out *AfdCustomDomain_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdCustomDomainOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -394,6 +437,43 @@ func (in *AfdEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdEndpointOperatorSpec) DeepCopyInto(out *AfdEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdEndpointOperatorSpec. +func (in *AfdEndpointOperatorSpec) DeepCopy() *AfdEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(AfdEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdEndpoint_STATUS) DeepCopyInto(out *AfdEndpoint_STATUS) { *out = *in @@ -496,6 +576,11 @@ func (in *AfdEndpoint_Spec) DeepCopyInto(out *AfdEndpoint_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -606,6 +691,43 @@ func (in *AfdOriginGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdOriginGroupOperatorSpec) DeepCopyInto(out *AfdOriginGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdOriginGroupOperatorSpec. +func (in *AfdOriginGroupOperatorSpec) DeepCopy() *AfdOriginGroupOperatorSpec { + if in == nil { + return nil + } + out := new(AfdOriginGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdOriginGroup_STATUS) DeepCopyInto(out *AfdOriginGroup_STATUS) { *out = *in @@ -696,6 +818,11 @@ func (in *AfdOriginGroup_Spec) DeepCopyInto(out *AfdOriginGroup_Spec) { *out = new(LoadBalancingSettingsParameters) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdOriginGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -755,6 +882,43 @@ func (in *AfdOriginList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AfdOriginOperatorSpec) DeepCopyInto(out *AfdOriginOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AfdOriginOperatorSpec. +func (in *AfdOriginOperatorSpec) DeepCopy() *AfdOriginOperatorSpec { + if in == nil { + return nil + } + out := new(AfdOriginOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AfdOrigin_STATUS) DeepCopyInto(out *AfdOrigin_STATUS) { *out = *in @@ -895,6 +1059,11 @@ func (in *AfdOrigin_Spec) DeepCopyInto(out *AfdOrigin_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AfdOriginOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginHostHeader != nil { in, out := &in.OriginHostHeader, &out.OriginHostHeader *out = new(string) @@ -4013,6 +4182,43 @@ func (in *ProfileList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProfileOperatorSpec) DeepCopyInto(out *ProfileOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileOperatorSpec. +func (in *ProfileOperatorSpec) DeepCopy() *ProfileOperatorSpec { + if in == nil { + return nil + } + out := new(ProfileOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Profile_STATUS) DeepCopyInto(out *Profile_STATUS) { *out = *in @@ -4122,6 +4328,11 @@ func (in *Profile_Spec) DeepCopyInto(out *Profile_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ProfileOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginResponseTimeoutSeconds != nil { in, out := &in.OriginResponseTimeoutSeconds, &out.OriginResponseTimeoutSeconds *out = new(int) @@ -4885,6 +5096,43 @@ func (in *RouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteOperatorSpec) DeepCopyInto(out *RouteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteOperatorSpec. +func (in *RouteOperatorSpec) DeepCopy() *RouteOperatorSpec { + if in == nil { + return nil + } + out := new(RouteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Route_STATUS) DeepCopyInto(out *Route_STATUS) { *out = *in @@ -5036,6 +5284,11 @@ func (in *Route_Spec) DeepCopyInto(out *Route_Spec) { *out = new(RouteProperties_LinkToDefaultDomain) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OriginGroup != nil { in, out := &in.OriginGroup, &out.OriginGroup *out = new(ResourceReference) @@ -5139,6 +5392,43 @@ func (in *RuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleOperatorSpec) DeepCopyInto(out *RuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleOperatorSpec. +func (in *RuleOperatorSpec) DeepCopy() *RuleOperatorSpec { + if in == nil { + return nil + } + out := new(RuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet) DeepCopyInto(out *RuleSet) { *out = *in @@ -5198,6 +5488,43 @@ func (in *RuleSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuleSetOperatorSpec) DeepCopyInto(out *RuleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuleSetOperatorSpec. +func (in *RuleSetOperatorSpec) DeepCopy() *RuleSetOperatorSpec { + if in == nil { + return nil + } + out := new(RuleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet_STATUS) DeepCopyInto(out *RuleSet_STATUS) { *out = *in @@ -5258,6 +5585,11 @@ func (in *RuleSet_STATUS) DeepCopy() *RuleSet_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuleSet_Spec) DeepCopyInto(out *RuleSet_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RuleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5371,6 +5703,11 @@ func (in *Rule_Spec) DeepCopyInto(out *Rule_Spec) { *out = new(RuleProperties_MatchProcessingBehavior) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Order != nil { in, out := &in.Order, &out.Order *out = new(int) @@ -5459,6 +5796,43 @@ func (in *SecretList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretOperatorSpec) DeepCopyInto(out *SecretOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretOperatorSpec. +func (in *SecretOperatorSpec) DeepCopy() *SecretOperatorSpec { + if in == nil { + return nil + } + out := new(SecretOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretParameters) DeepCopyInto(out *SecretParameters) { *out = *in @@ -5594,6 +5968,11 @@ func (in *Secret_STATUS) DeepCopy() *Secret_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret_Spec) DeepCopyInto(out *Secret_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SecretOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5675,6 +6054,43 @@ func (in *SecurityPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityPolicyOperatorSpec) DeepCopyInto(out *SecurityPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityPolicyOperatorSpec. +func (in *SecurityPolicyOperatorSpec) DeepCopy() *SecurityPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(SecurityPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityPolicyPropertiesParameters) DeepCopyInto(out *SecurityPolicyPropertiesParameters) { *out = *in @@ -5898,6 +6314,11 @@ func (in *SecurityPolicy_STATUS) DeepCopy() *SecurityPolicy_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecurityPolicy_Spec) DeepCopyInto(out *SecurityPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SecurityPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20200930/disk_types_gen.go b/v2/api/compute/v1api20200930/disk_types_gen.go index b9d20073ddc..bd60f8dafa9 100644 --- a/v2/api/compute/v1api20200930/disk_types_gen.go +++ b/v2/api/compute/v1api20200930/disk_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (disk *Disk) defaultAzureName() { // defaultImpl applies the code generated defaults to the Disk resource func (disk *Disk) defaultImpl() { disk.defaultAzureName() } +var _ configmaps.Exporter = &Disk{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (disk *Disk) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Disk{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (disk *Disk) SecretDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Disk{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (disk *Disk) ValidateUpdate(old runtime.Object) (admission.Warnings, error) // createValidations validates the creation of the resource func (disk *Disk) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){disk.validateResourceReferences, disk.validateOwnerReference} + return []func() (admission.Warnings, error){disk.validateResourceReferences, disk.validateOwnerReference, disk.validateSecretDestinations, disk.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (disk *Disk) updateValidations() []func(old runtime.Object) (admission.Warn func(old runtime.Object) (admission.Warnings, error) { return disk.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return disk.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return disk.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (disk *Disk) validateConfigMapDestinations() (admission.Warnings, error) { + if disk.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(disk, nil, disk.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (disk *Disk) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (disk *Disk) validateSecretDestinations() (admission.Warnings, error) { + if disk.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(disk, nil, disk.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (disk *Disk) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Disk) @@ -394,6 +439,10 @@ type Disk_Spec struct { // NetworkAccessPolicy: Policy for accessing the disk via network. NetworkAccessPolicy *NetworkAccessPolicy `json:"networkAccessPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiskOperatorSpec `json:"operatorSpec,omitempty"` + // OsType: The Operating System type. OsType *DiskProperties_OsType `json:"osType,omitempty"` @@ -745,6 +794,8 @@ func (disk *Disk_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, } } + // no assignment for property "OperatorSpec" + // Set property "OsType": // copying flattened property: if typedInput.Properties != nil { @@ -972,6 +1023,18 @@ func (disk *Disk_Spec) AssignProperties_From_Disk_Spec(source *storage.Disk_Spec disk.NetworkAccessPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskOperatorSpec + err := operatorSpec.AssignProperties_From_DiskOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskOperatorSpec() to populate field OperatorSpec") + } + disk.OperatorSpec = &operatorSpec + } else { + disk.OperatorSpec = nil + } + // OsType if source.OsType != nil { osType := *source.OsType @@ -1135,6 +1198,18 @@ func (disk *Disk_Spec) AssignProperties_To_Disk_Spec(destination *storage.Disk_S destination.NetworkAccessPolicy = nil } + // OperatorSpec + if disk.OperatorSpec != nil { + var operatorSpec storage.DiskOperatorSpec + err := disk.OperatorSpec.AssignProperties_To_DiskOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = disk.OriginalVersion() @@ -2651,6 +2726,110 @@ func (data *CreationData_STATUS) AssignProperties_To_CreationData_STATUS(destina return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskOperatorSpec populates our DiskOperatorSpec from the provided source DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_From_DiskOperatorSpec(source *storage.DiskOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiskOperatorSpec populates the provided destination DiskOperatorSpec from our DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_To_DiskOperatorSpec(destination *storage.DiskOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"V1","V2"} type DiskProperties_HyperVGeneration string diff --git a/v2/api/compute/v1api20200930/disk_types_gen_test.go b/v2/api/compute/v1api20200930/disk_types_gen_test.go index 94cc575bcf6..4c11f64fc5f 100644 --- a/v2/api/compute/v1api20200930/disk_types_gen_test.go +++ b/v2/api/compute/v1api20200930/disk_types_gen_test.go @@ -424,6 +424,102 @@ func AddRelatedPropertyGeneratorsForDisk(gens map[string]gopter.Gen) { gens["Status"] = Disk_STATUSGenerator() } +func Test_DiskOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskOperatorSpec to DiskOperatorSpec via AssignProperties_To_DiskOperatorSpec & AssignProperties_From_DiskOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskOperatorSpec tests if a specific instance of DiskOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20200930s.DiskOperatorSpec + err := copied.AssignProperties_To_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskOperatorSpec + err = actual.AssignProperties_From_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskOperatorSpec runs a test to see if a specific instance of DiskOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskOperatorSpec instances for property testing - lazily instantiated by DiskOperatorSpecGenerator() +var diskOperatorSpecGenerator gopter.Gen + +// DiskOperatorSpecGenerator returns a generator of DiskOperatorSpec instances for property testing. +func DiskOperatorSpecGenerator() gopter.Gen { + if diskOperatorSpecGenerator != nil { + return diskOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskOperatorSpec{}), generators) + + return diskOperatorSpecGenerator +} + func Test_DiskSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -924,6 +1020,7 @@ func AddRelatedPropertyGeneratorsForDisk_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["Sku"] = gen.PtrOf(DiskSkuGenerator()) } diff --git a/v2/api/compute/v1api20200930/snapshot_types_gen.go b/v2/api/compute/v1api20200930/snapshot_types_gen.go index ecfd0c40d7b..ad0fb624645 100644 --- a/v2/api/compute/v1api20200930/snapshot_types_gen.go +++ b/v2/api/compute/v1api20200930/snapshot_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (snapshot *Snapshot) defaultAzureName() { // defaultImpl applies the code generated defaults to the Snapshot resource func (snapshot *Snapshot) defaultImpl() { snapshot.defaultAzureName() } +var _ configmaps.Exporter = &Snapshot{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (snapshot *Snapshot) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Snapshot{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (snapshot *Snapshot) SecretDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Snapshot{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (snapshot *Snapshot) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (snapshot *Snapshot) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){snapshot.validateResourceReferences, snapshot.validateOwnerReference} + return []func() (admission.Warnings, error){snapshot.validateResourceReferences, snapshot.validateOwnerReference, snapshot.validateSecretDestinations, snapshot.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (snapshot *Snapshot) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return snapshot.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return snapshot.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return snapshot.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (snapshot *Snapshot) validateConfigMapDestinations() (admission.Warnings, error) { + if snapshot.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(snapshot, nil, snapshot.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (snapshot *Snapshot) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (snapshot *Snapshot) validateSecretDestinations() (admission.Warnings, error) { + if snapshot.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(snapshot, nil, snapshot.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (snapshot *Snapshot) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Snapshot) @@ -372,6 +417,10 @@ type Snapshot_Spec struct { // NetworkAccessPolicy: Policy for accessing the disk via network. NetworkAccessPolicy *NetworkAccessPolicy `json:"networkAccessPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SnapshotOperatorSpec `json:"operatorSpec,omitempty"` + // OsType: The Operating System type. OsType *SnapshotProperties_OsType `json:"osType,omitempty"` @@ -654,6 +703,8 @@ func (snapshot *Snapshot_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe } } + // no assignment for property "OperatorSpec" + // Set property "OsType": // copying flattened property: if typedInput.Properties != nil { @@ -861,6 +912,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_From_Snapshot_Spec(source *stora snapshot.NetworkAccessPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SnapshotOperatorSpec + err := operatorSpec.AssignProperties_From_SnapshotOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SnapshotOperatorSpec() to populate field OperatorSpec") + } + snapshot.OperatorSpec = &operatorSpec + } else { + snapshot.OperatorSpec = nil + } + // OsType if source.OsType != nil { osType := *source.OsType @@ -1011,6 +1074,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_To_Snapshot_Spec(destination *st destination.NetworkAccessPolicy = nil } + // OperatorSpec + if snapshot.OperatorSpec != nil { + var operatorSpec storage.SnapshotOperatorSpec + err := snapshot.OperatorSpec.AssignProperties_To_SnapshotOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SnapshotOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = snapshot.OriginalVersion() @@ -1801,6 +1876,110 @@ var diskState_Values = map[string]DiskState{ "unattached": DiskState_Unattached, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SnapshotOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SnapshotOperatorSpec populates our SnapshotOperatorSpec from the provided source SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_From_SnapshotOperatorSpec(source *storage.SnapshotOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SnapshotOperatorSpec populates the provided destination SnapshotOperatorSpec from our SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_To_SnapshotOperatorSpec(destination *storage.SnapshotOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"V1","V2"} type SnapshotProperties_HyperVGeneration string diff --git a/v2/api/compute/v1api20200930/snapshot_types_gen_test.go b/v2/api/compute/v1api20200930/snapshot_types_gen_test.go index a38b4e2895a..06f5aeba56f 100644 --- a/v2/api/compute/v1api20200930/snapshot_types_gen_test.go +++ b/v2/api/compute/v1api20200930/snapshot_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSnapshot(gens map[string]gopter.Gen) { gens["Status"] = Snapshot_STATUSGenerator() } +func Test_SnapshotOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SnapshotOperatorSpec to SnapshotOperatorSpec via AssignProperties_To_SnapshotOperatorSpec & AssignProperties_From_SnapshotOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSnapshotOperatorSpec tests if a specific instance of SnapshotOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20200930s.SnapshotOperatorSpec + err := copied.AssignProperties_To_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SnapshotOperatorSpec + err = actual.AssignProperties_From_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SnapshotOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SnapshotOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSnapshotOperatorSpec runs a test to see if a specific instance of SnapshotOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SnapshotOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SnapshotOperatorSpec instances for property testing - lazily instantiated by +// SnapshotOperatorSpecGenerator() +var snapshotOperatorSpecGenerator gopter.Gen + +// SnapshotOperatorSpecGenerator returns a generator of SnapshotOperatorSpec instances for property testing. +func SnapshotOperatorSpecGenerator() gopter.Gen { + if snapshotOperatorSpecGenerator != nil { + return snapshotOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + snapshotOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SnapshotOperatorSpec{}), generators) + + return snapshotOperatorSpecGenerator +} + func Test_SnapshotSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -648,6 +745,7 @@ func AddRelatedPropertyGeneratorsForSnapshot_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SnapshotOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["Sku"] = gen.PtrOf(SnapshotSkuGenerator()) } diff --git a/v2/api/compute/v1api20200930/storage/disk_types_gen.go b/v2/api/compute/v1api20200930/storage/disk_types_gen.go index e167615a90f..e7f99d07257 100644 --- a/v2/api/compute/v1api20200930/storage/disk_types_gen.go +++ b/v2/api/compute/v1api20200930/storage/disk_types_gen.go @@ -12,6 +12,9 @@ import ( v20240302s "github.com/Azure/azure-service-operator/v2/api/compute/v1api20240302/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -69,6 +72,26 @@ func (disk *Disk) ConvertTo(hub conversion.Hub) error { return disk.AssignProperties_To_Disk(destination) } +var _ configmaps.Exporter = &Disk{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (disk *Disk) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Disk{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (disk *Disk) SecretDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Disk{} // AzureName returns the Azure name of the resource @@ -263,6 +286,7 @@ type Disk_Spec struct { Location *string `json:"location,omitempty"` MaxShares *int `json:"maxShares,omitempty"` NetworkAccessPolicy *string `json:"networkAccessPolicy,omitempty"` + OperatorSpec *DiskOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OsType *string `json:"osType,omitempty"` @@ -457,6 +481,18 @@ func (disk *Disk_Spec) AssignProperties_From_Disk_Spec(source *v20240302s.Disk_S // NetworkAccessPolicy disk.NetworkAccessPolicy = genruntime.ClonePointerToString(source.NetworkAccessPolicy) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskOperatorSpec + err := operatorSpec.AssignProperties_From_DiskOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskOperatorSpec() to populate field OperatorSpec") + } + disk.OperatorSpec = &operatorSpec + } else { + disk.OperatorSpec = nil + } + // OptimizedForFrequentAttach if source.OptimizedForFrequentAttach != nil { propertyBag.Add("OptimizedForFrequentAttach", *source.OptimizedForFrequentAttach) @@ -699,6 +735,18 @@ func (disk *Disk_Spec) AssignProperties_To_Disk_Spec(destination *v20240302s.Dis // NetworkAccessPolicy destination.NetworkAccessPolicy = genruntime.ClonePointerToString(disk.NetworkAccessPolicy) + // OperatorSpec + if disk.OperatorSpec != nil { + var operatorSpec v20240302s.DiskOperatorSpec + err := disk.OperatorSpec.AssignProperties_To_DiskOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptimizedForFrequentAttach if propertyBag.Contains("OptimizedForFrequentAttach") { var optimizedForFrequentAttach bool @@ -2031,6 +2079,136 @@ func (data *CreationData_STATUS) AssignProperties_To_CreationData_STATUS(destina return nil } +// Storage version of v1api20200930.DiskOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskOperatorSpec populates our DiskOperatorSpec from the provided source DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_From_DiskOperatorSpec(source *v20240302s.DiskOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForDiskOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForDiskOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_DiskOperatorSpec populates the provided destination DiskOperatorSpec from our DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_To_DiskOperatorSpec(destination *v20240302s.DiskOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForDiskOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForDiskOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20200930.DiskSku // The disks sku name. Can be Standard_LRS, Premium_LRS, StandardSSD_LRS, or UltraSSD_LRS. type DiskSku struct { @@ -2929,6 +3107,11 @@ type augmentConversionForCreationData_STATUS interface { AssignPropertiesTo(dst *v20240302s.CreationData_STATUS) error } +type augmentConversionForDiskOperatorSpec interface { + AssignPropertiesFrom(src *v20240302s.DiskOperatorSpec) error + AssignPropertiesTo(dst *v20240302s.DiskOperatorSpec) error +} + type augmentConversionForDiskSku interface { AssignPropertiesFrom(src *v20240302s.DiskSku) error AssignPropertiesTo(dst *v20240302s.DiskSku) error diff --git a/v2/api/compute/v1api20200930/storage/disk_types_gen_test.go b/v2/api/compute/v1api20200930/storage/disk_types_gen_test.go index e4b4176e94c..c932bc5d843 100644 --- a/v2/api/compute/v1api20200930/storage/disk_types_gen_test.go +++ b/v2/api/compute/v1api20200930/storage/disk_types_gen_test.go @@ -411,6 +411,102 @@ func AddRelatedPropertyGeneratorsForDisk(gens map[string]gopter.Gen) { gens["Status"] = Disk_STATUSGenerator() } +func Test_DiskOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskOperatorSpec to DiskOperatorSpec via AssignProperties_To_DiskOperatorSpec & AssignProperties_From_DiskOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskOperatorSpec tests if a specific instance of DiskOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20240302s.DiskOperatorSpec + err := copied.AssignProperties_To_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskOperatorSpec + err = actual.AssignProperties_From_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskOperatorSpec runs a test to see if a specific instance of DiskOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskOperatorSpec instances for property testing - lazily instantiated by DiskOperatorSpecGenerator() +var diskOperatorSpecGenerator gopter.Gen + +// DiskOperatorSpecGenerator returns a generator of DiskOperatorSpec instances for property testing. +func DiskOperatorSpecGenerator() gopter.Gen { + if diskOperatorSpecGenerator != nil { + return diskOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskOperatorSpec{}), generators) + + return diskOperatorSpecGenerator +} + func Test_DiskSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -898,6 +994,7 @@ func AddRelatedPropertyGeneratorsForDisk_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["Sku"] = gen.PtrOf(DiskSkuGenerator()) } diff --git a/v2/api/compute/v1api20200930/storage/snapshot_types_gen.go b/v2/api/compute/v1api20200930/storage/snapshot_types_gen.go index 9786221282a..3411e34a06f 100644 --- a/v2/api/compute/v1api20200930/storage/snapshot_types_gen.go +++ b/v2/api/compute/v1api20200930/storage/snapshot_types_gen.go @@ -11,6 +11,9 @@ import ( v20240302s "github.com/Azure/azure-service-operator/v2/api/compute/v1api20240302/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -68,6 +71,26 @@ func (snapshot *Snapshot) ConvertTo(hub conversion.Hub) error { return snapshot.AssignProperties_To_Snapshot(destination) } +var _ configmaps.Exporter = &Snapshot{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (snapshot *Snapshot) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Snapshot{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (snapshot *Snapshot) SecretDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Snapshot{} // AzureName returns the Azure name of the resource @@ -252,6 +275,7 @@ type Snapshot_Spec struct { Incremental *bool `json:"incremental,omitempty"` Location *string `json:"location,omitempty"` NetworkAccessPolicy *string `json:"networkAccessPolicy,omitempty"` + OperatorSpec *SnapshotOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OsType *string `json:"osType,omitempty"` @@ -439,6 +463,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_From_Snapshot_Spec(source *v2024 // NetworkAccessPolicy snapshot.NetworkAccessPolicy = genruntime.ClonePointerToString(source.NetworkAccessPolicy) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SnapshotOperatorSpec + err := operatorSpec.AssignProperties_From_SnapshotOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SnapshotOperatorSpec() to populate field OperatorSpec") + } + snapshot.OperatorSpec = &operatorSpec + } else { + snapshot.OperatorSpec = nil + } + // OriginalVersion snapshot.OriginalVersion = source.OriginalVersion @@ -669,6 +705,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_To_Snapshot_Spec(destination *v2 // NetworkAccessPolicy destination.NetworkAccessPolicy = genruntime.ClonePointerToString(snapshot.NetworkAccessPolicy) + // OperatorSpec + if snapshot.OperatorSpec != nil { + var operatorSpec v20240302s.SnapshotOperatorSpec + err := snapshot.OperatorSpec.AssignProperties_To_SnapshotOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SnapshotOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = snapshot.OriginalVersion @@ -1374,6 +1422,136 @@ type augmentConversionForSnapshot_STATUS interface { AssignPropertiesTo(dst *v20240302s.Snapshot_STATUS) error } +// Storage version of v1api20200930.SnapshotOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SnapshotOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SnapshotOperatorSpec populates our SnapshotOperatorSpec from the provided source SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_From_SnapshotOperatorSpec(source *v20240302s.SnapshotOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSnapshotOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSnapshotOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SnapshotOperatorSpec populates the provided destination SnapshotOperatorSpec from our SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_To_SnapshotOperatorSpec(destination *v20240302s.SnapshotOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSnapshotOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSnapshotOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20200930.SnapshotSku // The snapshots sku name. Can be Standard_LRS, Premium_LRS, or Standard_ZRS. This is an optional parameter for incremental // snapshot and the default behavior is the SKU will be set to the same sku as the previous snapshot @@ -1509,6 +1687,11 @@ func (snapshotSku *SnapshotSku_STATUS) AssignProperties_To_SnapshotSku_STATUS(de return nil } +type augmentConversionForSnapshotOperatorSpec interface { + AssignPropertiesFrom(src *v20240302s.SnapshotOperatorSpec) error + AssignPropertiesTo(dst *v20240302s.SnapshotOperatorSpec) error +} + type augmentConversionForSnapshotSku interface { AssignPropertiesFrom(src *v20240302s.SnapshotSku) error AssignPropertiesTo(dst *v20240302s.SnapshotSku) error diff --git a/v2/api/compute/v1api20200930/storage/snapshot_types_gen_test.go b/v2/api/compute/v1api20200930/storage/snapshot_types_gen_test.go index bc1febb044f..4fe6292af0f 100644 --- a/v2/api/compute/v1api20200930/storage/snapshot_types_gen_test.go +++ b/v2/api/compute/v1api20200930/storage/snapshot_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForSnapshot(gens map[string]gopter.Gen) { gens["Status"] = Snapshot_STATUSGenerator() } +func Test_SnapshotOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SnapshotOperatorSpec to SnapshotOperatorSpec via AssignProperties_To_SnapshotOperatorSpec & AssignProperties_From_SnapshotOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSnapshotOperatorSpec tests if a specific instance of SnapshotOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SnapshotOperatorSpec + err := copied.AssignProperties_To_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SnapshotOperatorSpec + err = actual.AssignProperties_From_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SnapshotOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SnapshotOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSnapshotOperatorSpec runs a test to see if a specific instance of SnapshotOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SnapshotOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SnapshotOperatorSpec instances for property testing - lazily instantiated by +// SnapshotOperatorSpecGenerator() +var snapshotOperatorSpecGenerator gopter.Gen + +// SnapshotOperatorSpecGenerator returns a generator of SnapshotOperatorSpec instances for property testing. +func SnapshotOperatorSpecGenerator() gopter.Gen { + if snapshotOperatorSpecGenerator != nil { + return snapshotOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + snapshotOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SnapshotOperatorSpec{}), generators) + + return snapshotOperatorSpecGenerator +} + func Test_SnapshotSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -636,6 +733,7 @@ func AddRelatedPropertyGeneratorsForSnapshot_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SnapshotOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["Sku"] = gen.PtrOf(SnapshotSkuGenerator()) } diff --git a/v2/api/compute/v1api20200930/storage/structure.txt b/v2/api/compute/v1api20200930/storage/structure.txt index 0ffe616cf48..0d66ca9aad3 100644 --- a/v2/api/compute/v1api20200930/storage/structure.txt +++ b/v2/api/compute/v1api20200930/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-09-30" Disk: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (25 properties) +├── Spec: Object (26 properties) │ ├── AzureName: string │ ├── BurstingEnabled: *bool │ ├── CreationData: *Object (9 properties) @@ -60,6 +60,10 @@ Disk: Resource │ ├── Location: *string │ ├── MaxShares: *int │ ├── NetworkAccessPolicy: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsType: *string │ ├── Owner: *genruntime.KnownResourceReference @@ -162,7 +166,7 @@ Disk: Resource └── Zones: string[] Snapshot: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AzureName: string │ ├── CreationData: *Object (9 properties) │ │ ├── CreateOption: *string @@ -213,6 +217,10 @@ Snapshot: Resource │ ├── Incremental: *bool │ ├── Location: *string │ ├── NetworkAccessPolicy: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsType: *string │ ├── Owner: *genruntime.KnownResourceReference @@ -303,6 +311,7 @@ Snapshot: Resource augmentConversionForCreationData: Interface augmentConversionForCreationData_STATUS: Interface augmentConversionForDisk: Interface +augmentConversionForDiskOperatorSpec: Interface augmentConversionForDiskSku: Interface augmentConversionForDiskSku_STATUS: Interface augmentConversionForDisk_STATUS: Interface @@ -325,6 +334,7 @@ augmentConversionForPurchasePlan: Interface augmentConversionForPurchasePlan_STATUS: Interface augmentConversionForShareInfoElement_STATUS: Interface augmentConversionForSnapshot: Interface +augmentConversionForSnapshotOperatorSpec: Interface augmentConversionForSnapshotSku: Interface augmentConversionForSnapshotSku_STATUS: Interface augmentConversionForSnapshot_STATUS: Interface diff --git a/v2/api/compute/v1api20200930/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20200930/storage/zz_generated.deepcopy.go index 6a676943715..5bf44d3f23e 100644 --- a/v2/api/compute/v1api20200930/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20200930/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -203,6 +204,50 @@ func (in *DiskList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskOperatorSpec) DeepCopyInto(out *DiskOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskOperatorSpec. +func (in *DiskOperatorSpec) DeepCopy() *DiskOperatorSpec { + if in == nil { + return nil + } + out := new(DiskOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskSku) DeepCopyInto(out *DiskSku) { *out = *in @@ -533,6 +578,11 @@ func (in *Disk_Spec) DeepCopyInto(out *Disk_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(string) @@ -1221,6 +1271,50 @@ func (in *SnapshotList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotOperatorSpec) DeepCopyInto(out *SnapshotOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotOperatorSpec. +func (in *SnapshotOperatorSpec) DeepCopy() *SnapshotOperatorSpec { + if in == nil { + return nil + } + out := new(SnapshotOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SnapshotSku) DeepCopyInto(out *SnapshotSku) { *out = *in @@ -1484,6 +1578,11 @@ func (in *Snapshot_Spec) DeepCopyInto(out *Snapshot_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SnapshotOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(string) diff --git a/v2/api/compute/v1api20200930/structure.txt b/v2/api/compute/v1api20200930/structure.txt index 52b693be314..ebc13d49e1e 100644 --- a/v2/api/compute/v1api20200930/structure.txt +++ b/v2/api/compute/v1api20200930/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-09-30" Disk: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (23 properties) +├── Spec: Object (24 properties) │ ├── AzureName: string │ ├── BurstingEnabled: *bool │ ├── CreationData: *Object (8 properties) @@ -65,6 +65,9 @@ Disk: Resource │ │ ├── "AllowAll" │ │ ├── "AllowPrivate" │ │ └── "DenyAll" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsType: *Enum (2 values) │ │ ├── "Linux" │ │ └── "Windows" @@ -182,7 +185,7 @@ Disk: Resource └── Zones: string[] Snapshot: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AzureName: string │ ├── CreationData: *Object (8 properties) │ │ ├── CreateOption: *Enum (7 values) @@ -244,6 +247,9 @@ Snapshot: Resource │ │ ├── "AllowAll" │ │ ├── "AllowPrivate" │ │ └── "DenyAll" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsType: *Enum (2 values) │ │ ├── "Linux" │ │ └── "Windows" diff --git a/v2/api/compute/v1api20200930/zz_generated.deepcopy.go b/v2/api/compute/v1api20200930/zz_generated.deepcopy.go index 1a19a33d56a..9004a290fa1 100644 --- a/v2/api/compute/v1api20200930/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20200930/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20200930 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -189,6 +190,43 @@ func (in *DiskList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskOperatorSpec) DeepCopyInto(out *DiskOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskOperatorSpec. +func (in *DiskOperatorSpec) DeepCopy() *DiskOperatorSpec { + if in == nil { + return nil + } + out := new(DiskOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskSku) DeepCopyInto(out *DiskSku) { *out = *in @@ -498,6 +536,11 @@ func (in *Disk_Spec) DeepCopyInto(out *Disk_Spec) { *out = new(NetworkAccessPolicy) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(DiskProperties_OsType) @@ -1060,6 +1103,43 @@ func (in *SnapshotList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotOperatorSpec) DeepCopyInto(out *SnapshotOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotOperatorSpec. +func (in *SnapshotOperatorSpec) DeepCopy() *SnapshotOperatorSpec { + if in == nil { + return nil + } + out := new(SnapshotOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SnapshotSku) DeepCopyInto(out *SnapshotSku) { *out = *in @@ -1302,6 +1382,11 @@ func (in *Snapshot_Spec) DeepCopyInto(out *Snapshot_Spec) { *out = new(NetworkAccessPolicy) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SnapshotOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(SnapshotProperties_OsType) diff --git a/v2/api/compute/v1api20201201/storage/structure.txt b/v2/api/compute/v1api20201201/storage/structure.txt index 1bd18420af5..e651e5bc203 100644 --- a/v2/api/compute/v1api20201201/storage/structure.txt +++ b/v2/api/compute/v1api20201201/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-12-01" VirtualMachine: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (28 properties) +├── Spec: Object (29 properties) │ ├── AdditionalCapabilities: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── UltraSSDEnabled: *bool @@ -51,6 +51,10 @@ VirtualMachine: Resource │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── Reference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsProfile: *Object (10 properties) │ │ ├── AdminPassword: *genruntime.SecretReference @@ -610,7 +614,7 @@ VirtualMachine: Resource └── Zones: string[] VirtualMachineScaleSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (24 properties) +├── Spec: Object (25 properties) │ ├── AdditionalCapabilities: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── UltraSSDEnabled: *bool @@ -634,6 +638,10 @@ VirtualMachineScaleSet: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestrationMode: *string │ ├── OriginalVersion: string │ ├── Overprovision: *bool @@ -1140,11 +1148,15 @@ VirtualMachineScaleSet: Resource └── Zones: string[] VirtualMachineScaleSetsExtension: Resource ├── Owner: compute/v1api20201201.VirtualMachineScaleSet -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool │ ├── ForceUpdateTag: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1171,7 +1183,7 @@ VirtualMachineScaleSetsExtension: Resource └── TypeHandlerVersion: *string VirtualMachinesExtension: Resource ├── Owner: compute/v1api20201201.VirtualMachine -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool @@ -1196,6 +1208,10 @@ VirtualMachinesExtension: Resource │ │ ├── Type: *string │ │ └── TypeHandlerVersion: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1342,6 +1358,7 @@ augmentConversionForVirtualMachineIdentity: Interface augmentConversionForVirtualMachineIdentity_STATUS: Interface augmentConversionForVirtualMachineIdentity_UserAssignedIdentities_STATUS: Interface augmentConversionForVirtualMachineInstanceView_STATUS: Interface +augmentConversionForVirtualMachineOperatorSpec: Interface augmentConversionForVirtualMachinePatchStatus_STATUS: Interface augmentConversionForVirtualMachineScaleSet: Interface augmentConversionForVirtualMachineScaleSetDataDisk: Interface @@ -1369,6 +1386,7 @@ augmentConversionForVirtualMachineScaleSetOSDisk: Interface augmentConversionForVirtualMachineScaleSetOSDisk_STATUS: Interface augmentConversionForVirtualMachineScaleSetOSProfile: Interface augmentConversionForVirtualMachineScaleSetOSProfile_STATUS: Interface +augmentConversionForVirtualMachineScaleSetOperatorSpec: Interface augmentConversionForVirtualMachineScaleSetPublicIPAddressConfiguration: Interface augmentConversionForVirtualMachineScaleSetPublicIPAddressConfigurationDnsSettings: Interface augmentConversionForVirtualMachineScaleSetPublicIPAddressConfigurationDnsSettings_STATUS: Interface @@ -1380,11 +1398,13 @@ augmentConversionForVirtualMachineScaleSetVMProfile_STATUS: Interface augmentConversionForVirtualMachineScaleSet_STATUS: Interface augmentConversionForVirtualMachineScaleSet_Spec: Interface augmentConversionForVirtualMachineScaleSetsExtension: Interface +augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec: Interface augmentConversionForVirtualMachineScaleSetsExtension_STATUS: Interface augmentConversionForVirtualMachineScaleSetsExtension_Spec: Interface augmentConversionForVirtualMachine_STATUS: Interface augmentConversionForVirtualMachine_Spec: Interface augmentConversionForVirtualMachinesExtension: Interface +augmentConversionForVirtualMachinesExtensionOperatorSpec: Interface augmentConversionForVirtualMachinesExtension_STATUS: Interface augmentConversionForVirtualMachinesExtension_Spec: Interface augmentConversionForWinRMConfiguration: Interface diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen.go b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen.go index f736b07ec25..26f0a4ff581 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen.go @@ -9,6 +9,9 @@ import ( v20220301s "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220301/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -67,6 +70,26 @@ func (scaleSet *VirtualMachineScaleSet) ConvertTo(hub conversion.Hub) error { return scaleSet.AssignProperties_To_VirtualMachineScaleSet(destination) } +var _ configmaps.Exporter = &VirtualMachineScaleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (scaleSet *VirtualMachineScaleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (scaleSet *VirtualMachineScaleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSet{} // AzureName returns the Azure name of the resource @@ -240,15 +263,16 @@ type VirtualMachineScaleSet_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DoNotRunExtensionsOnOverprovisionedVMs *bool `json:"doNotRunExtensionsOnOverprovisionedVMs,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - HostGroup *SubResource `json:"hostGroup,omitempty"` - Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"` - Location *string `json:"location,omitempty"` - OrchestrationMode *string `json:"orchestrationMode,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - Overprovision *bool `json:"overprovision,omitempty"` + AzureName string `json:"azureName,omitempty"` + DoNotRunExtensionsOnOverprovisionedVMs *bool `json:"doNotRunExtensionsOnOverprovisionedVMs,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + HostGroup *SubResource `json:"hostGroup,omitempty"` + Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VirtualMachineScaleSetOperatorSpec `json:"operatorSpec,omitempty"` + OrchestrationMode *string `json:"orchestrationMode,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + Overprovision *bool `json:"overprovision,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -408,6 +432,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_From_VirtualMachin // Location scaleSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + scaleSet.OperatorSpec = &operatorSpec + } else { + scaleSet.OperatorSpec = nil + } + // OrchestrationMode scaleSet.OrchestrationMode = genruntime.ClonePointerToString(source.OrchestrationMode) @@ -648,6 +684,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_To_VirtualMachineS // Location destination.Location = genruntime.ClonePointerToString(scaleSet.Location) + // OperatorSpec + if scaleSet.OperatorSpec != nil { + var operatorSpec v20220301s.VirtualMachineScaleSetOperatorSpec + err := scaleSet.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestrationMode destination.OrchestrationMode = genruntime.ClonePointerToString(scaleSet.OrchestrationMode) @@ -2373,6 +2421,136 @@ func (identity *VirtualMachineScaleSetIdentity_STATUS) AssignProperties_To_Virtu return nil } +// Storage version of v1api20201201.VirtualMachineScaleSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetOperatorSpec populates our VirtualMachineScaleSetOperatorSpec from the provided source VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source *v20220301s.VirtualMachineScaleSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineScaleSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineScaleSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetOperatorSpec populates the provided destination VirtualMachineScaleSetOperatorSpec from our VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_To_VirtualMachineScaleSetOperatorSpec(destination *v20220301s.VirtualMachineScaleSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineScaleSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineScaleSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20201201.VirtualMachineScaleSetVMProfile // Describes a virtual machine scale set virtual machine profile. type VirtualMachineScaleSetVMProfile struct { @@ -3137,6 +3315,11 @@ type augmentConversionForVirtualMachineScaleSetIdentity_STATUS interface { AssignPropertiesTo(dst *v20220301s.VirtualMachineScaleSetIdentity_STATUS) error } +type augmentConversionForVirtualMachineScaleSetOperatorSpec interface { + AssignPropertiesFrom(src *v20220301s.VirtualMachineScaleSetOperatorSpec) error + AssignPropertiesTo(dst *v20220301s.VirtualMachineScaleSetOperatorSpec) error +} + type augmentConversionForVirtualMachineScaleSetVMProfile interface { AssignPropertiesFrom(src *v20220301s.VirtualMachineScaleSetVMProfile) error AssignPropertiesTo(dst *v20220301s.VirtualMachineScaleSetVMProfile) error diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen_test.go b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen_test.go index c2d5615eda1..bf8798c9e38 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen_test.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_set_types_gen_test.go @@ -4949,6 +4949,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetOSProfile_STATUS(gens gens["WindowsConfiguration"] = gen.PtrOf(WindowsConfiguration_STATUSGenerator()) } +func Test_VirtualMachineScaleSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetOperatorSpec to VirtualMachineScaleSetOperatorSpec via AssignProperties_To_VirtualMachineScaleSetOperatorSpec & AssignProperties_From_VirtualMachineScaleSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec tests if a specific instance of VirtualMachineScaleSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachineScaleSetOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetOperatorSpecGenerator() +var virtualMachineScaleSetOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetOperatorSpecGenerator returns a generator of VirtualMachineScaleSetOperatorSpec instances for property testing. +func VirtualMachineScaleSetOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetOperatorSpecGenerator != nil { + return virtualMachineScaleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetOperatorSpec{}), generators) + + return virtualMachineScaleSetOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetPublicIPAddressConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -6132,6 +6229,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSet_Spec(gens map[string] gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineScaleSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetOperatorSpecGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) gens["ScaleInPolicy"] = gen.PtrOf(ScaleInPolicyGenerator()) diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen.go b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen.go index 673611b39ea..2724e9c4441 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220301/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -66,6 +69,26 @@ func (extension *VirtualMachineScaleSetsExtension) ConvertTo(hub conversion.Hub) return extension.AssignProperties_To_VirtualMachineScaleSetsExtension(destination) } +var _ configmaps.Exporter = &VirtualMachineScaleSetsExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachineScaleSetsExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSetsExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachineScaleSetsExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSetsExtension{} // AzureName returns the Azure name of the resource @@ -238,10 +261,11 @@ type VirtualMachineScaleSetsExtension_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` - ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` + ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + OperatorSpec *VirtualMachineScaleSetsExtensionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -334,6 +358,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_From_Vi // ForceUpdateTag extension.ForceUpdateTag = genruntime.ClonePointerToString(source.ForceUpdateTag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetsExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // OriginalVersion extension.OriginalVersion = source.OriginalVersion @@ -439,6 +475,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_To_Virt // ForceUpdateTag destination.ForceUpdateTag = genruntime.ClonePointerToString(extension.ForceUpdateTag) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineScaleSetsExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion @@ -815,6 +863,141 @@ type augmentConversionForVirtualMachineScaleSetsExtension_STATUS interface { AssignPropertiesTo(dst *storage.VirtualMachineScaleSetsExtension_STATUS) error } +// Storage version of v1api20201201.VirtualMachineScaleSetsExtensionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetsExtensionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec populates our VirtualMachineScaleSetsExtensionOperatorSpec from the provided source VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec populates the provided destination VirtualMachineScaleSetsExtensionOperatorSpec from our VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(destination *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForVirtualMachineScaleSetsExtensionOperatorSpec interface { + AssignPropertiesFrom(src *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error + AssignPropertiesTo(dst *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error +} + func init() { SchemeBuilder.Register(&VirtualMachineScaleSetsExtension{}, &VirtualMachineScaleSetsExtensionList{}) } diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen_test.go b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen_test.go index e043f0cac05..90d7ebf709d 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen_test.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_scale_sets_extension_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension(gens map[st gens["Status"] = VirtualMachineScaleSetsExtension_STATUSGenerator() } +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetsExtensionOperatorSpec to VirtualMachineScaleSetsExtensionOperatorSpec via AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec & AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec tests if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachineScaleSetsExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetsExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator() +var virtualMachineScaleSetsExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator returns a generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing. +func VirtualMachineScaleSetsExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetsExtensionOperatorSpecGenerator != nil { + return virtualMachineScaleSetsExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetsExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtensionOperatorSpec{}), generators) + + return virtualMachineScaleSetsExtensionOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetsExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -364,6 +461,9 @@ func RunJSONSerializationTestForVirtualMachineScaleSetsExtension_Spec(subject Vi var virtualMachineScaleSetsExtension_SpecGenerator gopter.Gen // VirtualMachineScaleSetsExtension_SpecGenerator returns a generator of VirtualMachineScaleSetsExtension_Spec instances for property testing. +// We first initialize virtualMachineScaleSetsExtension_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func VirtualMachineScaleSetsExtension_SpecGenerator() gopter.Gen { if virtualMachineScaleSetsExtension_SpecGenerator != nil { return virtualMachineScaleSetsExtension_SpecGenerator @@ -373,6 +473,12 @@ func VirtualMachineScaleSetsExtension_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) virtualMachineScaleSetsExtension_SpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtension_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) + AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) + virtualMachineScaleSetsExtension_SpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtension_Spec{}), generators) + return virtualMachineScaleSetsExtension_SpecGenerator } @@ -388,3 +494,8 @@ func AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(ge gens["Type"] = gen.PtrOf(gen.AlphaString()) gens["TypeHandlerVersion"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetsExtensionOperatorSpecGenerator()) +} diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen.go b/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen.go index 6894fe13920..1a7c1e89ab5 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen.go @@ -9,6 +9,9 @@ import ( v20220301s "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220301/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -67,6 +70,26 @@ func (machine *VirtualMachine) ConvertTo(hub conversion.Hub) error { return machine.AssignProperties_To_VirtualMachine(destination) } +var _ configmaps.Exporter = &VirtualMachine{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (machine *VirtualMachine) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachine{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (machine *VirtualMachine) SecretDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachine{} // AzureName returns the Azure name of the resource @@ -246,21 +269,22 @@ type VirtualMachine_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - BillingProfile *BillingProfile `json:"billingProfile,omitempty"` - DiagnosticsProfile *DiagnosticsProfile `json:"diagnosticsProfile,omitempty"` - EvictionPolicy *string `json:"evictionPolicy,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - ExtensionsTimeBudget *string `json:"extensionsTimeBudget,omitempty"` - HardwareProfile *HardwareProfile `json:"hardwareProfile,omitempty"` - Host *SubResource `json:"host,omitempty"` - HostGroup *SubResource `json:"hostGroup,omitempty"` - Identity *VirtualMachineIdentity `json:"identity,omitempty"` - LicenseType *string `json:"licenseType,omitempty"` - Location *string `json:"location,omitempty"` - NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsProfile *OSProfile `json:"osProfile,omitempty"` + AzureName string `json:"azureName,omitempty"` + BillingProfile *BillingProfile `json:"billingProfile,omitempty"` + DiagnosticsProfile *DiagnosticsProfile `json:"diagnosticsProfile,omitempty"` + EvictionPolicy *string `json:"evictionPolicy,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + ExtensionsTimeBudget *string `json:"extensionsTimeBudget,omitempty"` + HardwareProfile *HardwareProfile `json:"hardwareProfile,omitempty"` + Host *SubResource `json:"host,omitempty"` + HostGroup *SubResource `json:"hostGroup,omitempty"` + Identity *VirtualMachineIdentity `json:"identity,omitempty"` + LicenseType *string `json:"licenseType,omitempty"` + Location *string `json:"location,omitempty"` + NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + OperatorSpec *VirtualMachineOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsProfile *OSProfile `json:"osProfile,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -503,6 +527,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_From_VirtualMachine_Spec(so machine.NetworkProfile = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + machine.OperatorSpec = &operatorSpec + } else { + machine.OperatorSpec = nil + } + // OriginalVersion machine.OriginalVersion = source.OriginalVersion @@ -828,6 +864,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_To_VirtualMachine_Spec(dest destination.NetworkProfile = nil } + // OperatorSpec + if machine.OperatorSpec != nil { + var operatorSpec v20220301s.VirtualMachineOperatorSpec + err := machine.OperatorSpec.AssignProperties_To_VirtualMachineOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = machine.OriginalVersion @@ -4920,6 +4968,136 @@ func (view *VirtualMachineInstanceView_STATUS) AssignProperties_To_VirtualMachin return nil } +// Storage version of v1api20201201.VirtualMachineOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineOperatorSpec populates our VirtualMachineOperatorSpec from the provided source VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_From_VirtualMachineOperatorSpec(source *v20220301s.VirtualMachineOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineOperatorSpec populates the provided destination VirtualMachineOperatorSpec from our VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_To_VirtualMachineOperatorSpec(destination *v20220301s.VirtualMachineOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachineOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachineOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForAdditionalCapabilities interface { AssignPropertiesFrom(src *v20220301s.AdditionalCapabilities) error AssignPropertiesTo(dst *v20220301s.AdditionalCapabilities) error @@ -5050,6 +5228,11 @@ type augmentConversionForVirtualMachineInstanceView_STATUS interface { AssignPropertiesTo(dst *v20220301s.VirtualMachineInstanceView_STATUS) error } +type augmentConversionForVirtualMachineOperatorSpec interface { + AssignPropertiesFrom(src *v20220301s.VirtualMachineOperatorSpec) error + AssignPropertiesTo(dst *v20220301s.VirtualMachineOperatorSpec) error +} + // Storage version of v1api20201201.BootDiagnostics // Boot Diagnostics is a debugging feature which allows you to view Console Output and Screenshot to diagnose VM status. // You can easily view the output of your console log. diff --git a/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen_test.go b/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen_test.go index 45059531ed1..6f6be3807a3 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen_test.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machine_types_gen_test.go @@ -8935,6 +8935,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineInstanceView_STATUS(gens map[s gens["VmHealth"] = gen.PtrOf(VirtualMachineHealthStatus_STATUSGenerator()) } +func Test_VirtualMachineOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineOperatorSpec to VirtualMachineOperatorSpec via AssignProperties_To_VirtualMachineOperatorSpec & AssignProperties_From_VirtualMachineOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineOperatorSpec tests if a specific instance of VirtualMachineOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220301s.VirtualMachineOperatorSpec + err := copied.AssignProperties_To_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineOperatorSpec + err = actual.AssignProperties_From_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineOperatorSpec runs a test to see if a specific instance of VirtualMachineOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineOperatorSpecGenerator() +var virtualMachineOperatorSpecGenerator gopter.Gen + +// VirtualMachineOperatorSpecGenerator returns a generator of VirtualMachineOperatorSpec instances for property testing. +func VirtualMachineOperatorSpecGenerator() gopter.Gen { + if virtualMachineOperatorSpecGenerator != nil { + return virtualMachineOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineOperatorSpec{}), generators) + + return virtualMachineOperatorSpecGenerator +} + func Test_VirtualMachinePatchStatus_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -9323,6 +9420,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachine_Spec(gens map[string]gopter.G gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineIdentityGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineOperatorSpecGenerator()) gens["OsProfile"] = gen.PtrOf(OSProfileGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen.go b/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen.go index 9ad859940c6..17532deb74b 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220301/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -66,6 +69,26 @@ func (extension *VirtualMachinesExtension) ConvertTo(hub conversion.Hub) error { return extension.AssignProperties_To_VirtualMachinesExtension(destination) } +var _ configmaps.Exporter = &VirtualMachinesExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachinesExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachinesExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachinesExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachinesExtension{} // AzureName returns the Azure name of the resource @@ -238,12 +261,13 @@ type VirtualMachinesExtension_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` - ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` - InstanceView *VirtualMachineExtensionInstanceView `json:"instanceView,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` + ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + InstanceView *VirtualMachineExtensionInstanceView `json:"instanceView,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VirtualMachinesExtensionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -351,6 +375,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_From_VirtualMac // Location extension.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachinesExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // OriginalVersion extension.OriginalVersion = source.OriginalVersion @@ -471,6 +507,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_To_VirtualMachi // Location destination.Location = genruntime.ClonePointerToString(extension.Location) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachinesExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion @@ -1181,6 +1229,136 @@ func (view *VirtualMachineExtensionInstanceView_STATUS) AssignProperties_To_Virt return nil } +// Storage version of v1api20201201.VirtualMachinesExtensionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachinesExtensionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachinesExtensionOperatorSpec populates our VirtualMachinesExtensionOperatorSpec from the provided source VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source *storage.VirtualMachinesExtensionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachinesExtensionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachinesExtensionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachinesExtensionOperatorSpec populates the provided destination VirtualMachinesExtensionOperatorSpec from our VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_To_VirtualMachinesExtensionOperatorSpec(destination *storage.VirtualMachinesExtensionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForVirtualMachinesExtensionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVirtualMachinesExtensionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForVirtualMachineExtensionInstanceView interface { AssignPropertiesFrom(src *storage.VirtualMachineExtensionInstanceView) error AssignPropertiesTo(dst *storage.VirtualMachineExtensionInstanceView) error @@ -1191,6 +1369,11 @@ type augmentConversionForVirtualMachineExtensionInstanceView_STATUS interface { AssignPropertiesTo(dst *storage.VirtualMachineExtensionInstanceView_STATUS) error } +type augmentConversionForVirtualMachinesExtensionOperatorSpec interface { + AssignPropertiesFrom(src *storage.VirtualMachinesExtensionOperatorSpec) error + AssignPropertiesTo(dst *storage.VirtualMachinesExtensionOperatorSpec) error +} + // Storage version of v1api20201201.InstanceViewStatus // Instance view status. type InstanceViewStatus struct { diff --git a/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen_test.go b/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen_test.go index 138b617b70e..4f608db0d60 100644 --- a/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen_test.go +++ b/v2/api/compute/v1api20201201/storage/virtual_machines_extension_types_gen_test.go @@ -511,6 +511,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachinesExtension(gens map[string]gop gens["Status"] = VirtualMachinesExtension_STATUSGenerator() } +func Test_VirtualMachinesExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachinesExtensionOperatorSpec to VirtualMachinesExtensionOperatorSpec via AssignProperties_To_VirtualMachinesExtensionOperatorSpec & AssignProperties_From_VirtualMachinesExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec tests if a specific instance of VirtualMachinesExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachinesExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachinesExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachinesExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachinesExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachinesExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachinesExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachinesExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachinesExtensionOperatorSpecGenerator() +var virtualMachinesExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachinesExtensionOperatorSpecGenerator returns a generator of VirtualMachinesExtensionOperatorSpec instances for property testing. +func VirtualMachinesExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachinesExtensionOperatorSpecGenerator != nil { + return virtualMachinesExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachinesExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachinesExtensionOperatorSpec{}), generators) + + return virtualMachinesExtensionOperatorSpecGenerator +} + func Test_VirtualMachinesExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -767,4 +864,5 @@ func AddIndependentPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[s // AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[string]gopter.Gen) { gens["InstanceView"] = gen.PtrOf(VirtualMachineExtensionInstanceViewGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachinesExtensionOperatorSpecGenerator()) } diff --git a/v2/api/compute/v1api20201201/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20201201/storage/zz_generated.deepcopy.go index 72bbf6f28ee..52172c3c582 100644 --- a/v2/api/compute/v1api20201201/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20201201/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -4015,6 +4016,50 @@ func (in *VirtualMachineList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineOperatorSpec) DeepCopyInto(out *VirtualMachineOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineOperatorSpec. +func (in *VirtualMachineOperatorSpec) DeepCopy() *VirtualMachineOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinePatchStatus_STATUS) DeepCopyInto(out *VirtualMachinePatchStatus_STATUS) { *out = *in @@ -5388,6 +5433,50 @@ func (in *VirtualMachineScaleSetOSProfile_STATUS) DeepCopy() *VirtualMachineScal return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetOperatorSpec. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopy() *VirtualMachineScaleSetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetPublicIPAddressConfiguration) DeepCopyInto(out *VirtualMachineScaleSetPublicIPAddressConfiguration) { *out = *in @@ -5976,6 +6065,11 @@ func (in *VirtualMachineScaleSet_Spec) DeepCopyInto(out *VirtualMachineScaleSet_ *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestrationMode != nil { in, out := &in.OrchestrationMode, &out.OrchestrationMode *out = new(string) @@ -6126,6 +6220,50 @@ func (in *VirtualMachineScaleSetsExtensionList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetsExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetsExtensionOperatorSpec. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopy() *VirtualMachineScaleSetsExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetsExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetsExtension_STATUS) DeepCopyInto(out *VirtualMachineScaleSetsExtension_STATUS) { *out = *in @@ -6235,6 +6373,11 @@ func (in *VirtualMachineScaleSetsExtension_Spec) DeepCopyInto(out *VirtualMachin *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetsExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6552,6 +6695,11 @@ func (in *VirtualMachine_Spec) DeepCopyInto(out *VirtualMachine_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsProfile != nil { in, out := &in.OsProfile, &out.OsProfile *out = new(OSProfile) @@ -6687,6 +6835,50 @@ func (in *VirtualMachinesExtensionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopyInto(out *VirtualMachinesExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachinesExtensionOperatorSpec. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopy() *VirtualMachinesExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachinesExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinesExtension_STATUS) DeepCopyInto(out *VirtualMachinesExtension_STATUS) { *out = *in @@ -6818,6 +7010,11 @@ func (in *VirtualMachinesExtension_Spec) DeepCopyInto(out *VirtualMachinesExtens *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachinesExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20201201/structure.txt b/v2/api/compute/v1api20201201/structure.txt index ee67f812976..b477b4d3093 100644 --- a/v2/api/compute/v1api20201201/structure.txt +++ b/v2/api/compute/v1api20201201/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-12-01" VirtualMachine: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (26 properties) +├── Spec: Object (27 properties) │ ├── AdditionalCapabilities: *Object (1 property) │ │ └── UltraSSDEnabled: *bool │ ├── AvailabilitySet: *Object (1 property) @@ -45,6 +45,9 @@ VirtualMachine: Resource │ │ └── NetworkInterfaces: Object (2 properties)[] │ │ ├── Primary: *bool │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsProfile: *Object (9 properties) │ │ ├── AdminPassword: *genruntime.SecretReference │ │ ├── AdminUsername: *string @@ -793,7 +796,7 @@ VirtualMachine: Resource └── Zones: string[] VirtualMachineScaleSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (22 properties) +├── Spec: Object (23 properties) │ ├── AdditionalCapabilities: *Object (1 property) │ │ └── UltraSSDEnabled: *bool │ ├── AutomaticRepairsPolicy: *Object (2 properties) @@ -816,6 +819,9 @@ VirtualMachineScaleSet: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestrationMode: *Enum (2 values) │ │ ├── "Flexible" │ │ └── "Uniform" @@ -1330,11 +1336,14 @@ VirtualMachineScaleSet: Resource └── Zones: string[] VirtualMachineScaleSetsExtension: Resource ├── Owner: VirtualMachineScaleSet -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool │ ├── ForceUpdateTag: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtectedSettings: *genruntime.SecretMapReference │ ├── ProvisionAfterExtensions: string[] @@ -1358,7 +1367,7 @@ VirtualMachineScaleSetsExtension: Resource └── TypeHandlerVersion: *string VirtualMachinesExtension: Resource ├── Owner: VirtualMachine -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool @@ -1386,6 +1395,9 @@ VirtualMachinesExtension: Resource │ │ ├── Type: *string │ │ └── TypeHandlerVersion: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtectedSettings: *genruntime.SecretMapReference │ ├── Publisher: *string diff --git a/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen.go b/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen.go index 87525a68607..03c6f52ee36 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen.go +++ b/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +109,26 @@ func (scaleSet *VirtualMachineScaleSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachineScaleSet resource func (scaleSet *VirtualMachineScaleSet) defaultImpl() { scaleSet.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachineScaleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (scaleSet *VirtualMachineScaleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (scaleSet *VirtualMachineScaleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSet{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (scaleSet *VirtualMachineScaleSet) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (scaleSet *VirtualMachineScaleSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){scaleSet.validateResourceReferences, scaleSet.validateOwnerReference} + return []func() (admission.Warnings, error){scaleSet.validateResourceReferences, scaleSet.validateOwnerReference, scaleSet.validateSecretDestinations, scaleSet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (scaleSet *VirtualMachineScaleSet) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return scaleSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return scaleSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return scaleSet.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (scaleSet *VirtualMachineScaleSet) validateConfigMapDestinations() (admission.Warnings, error) { + if scaleSet.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(scaleSet, nil, scaleSet.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (scaleSet *VirtualMachineScaleSet) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (scaleSet *VirtualMachineScaleSet) validateSecretDestinations() (admission.Warnings, error) { + if scaleSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(scaleSet, nil, scaleSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (scaleSet *VirtualMachineScaleSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachineScaleSet) @@ -361,6 +406,10 @@ type VirtualMachineScaleSet_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineScaleSetOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestrationMode: Specifies the orchestration mode for the virtual machine scale set. OrchestrationMode *OrchestrationMode `json:"orchestrationMode,omitempty"` @@ -681,6 +730,8 @@ func (scaleSet *VirtualMachineScaleSet_Spec) PopulateFromARM(owner genruntime.Ar scaleSet.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OrchestrationMode": // copying flattened property: if typedInput.Properties != nil { @@ -956,6 +1007,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_From_VirtualMachin // Location scaleSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + scaleSet.OperatorSpec = &operatorSpec + } else { + scaleSet.OperatorSpec = nil + } + // OrchestrationMode if source.OrchestrationMode != nil { orchestrationMode := *source.OrchestrationMode @@ -1161,6 +1224,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_To_VirtualMachineS // Location destination.Location = genruntime.ClonePointerToString(scaleSet.Location) + // OperatorSpec + if scaleSet.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineScaleSetOperatorSpec + err := scaleSet.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestrationMode if scaleSet.OrchestrationMode != nil { orchestrationMode := string(*scaleSet.OrchestrationMode) @@ -3432,6 +3507,110 @@ func (identity *VirtualMachineScaleSetIdentity_STATUS) AssignProperties_To_Virtu return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetOperatorSpec populates our VirtualMachineScaleSetOperatorSpec from the provided source VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source *storage.VirtualMachineScaleSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetOperatorSpec populates the provided destination VirtualMachineScaleSetOperatorSpec from our VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_To_VirtualMachineScaleSetOperatorSpec(destination *storage.VirtualMachineScaleSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Describes a virtual machine scale set virtual machine profile. type VirtualMachineScaleSetVMProfile struct { // BillingProfile: Specifies the billing related details of a Azure Spot VMSS. diff --git a/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen_test.go b/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen_test.go index 0ea79860502..301ad137f03 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen_test.go +++ b/v2/api/compute/v1api20201201/virtual_machine_scale_set_types_gen_test.go @@ -4970,6 +4970,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetOSProfile_STATUS(gens gens["WindowsConfiguration"] = gen.PtrOf(WindowsConfiguration_STATUSGenerator()) } +func Test_VirtualMachineScaleSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetOperatorSpec to VirtualMachineScaleSetOperatorSpec via AssignProperties_To_VirtualMachineScaleSetOperatorSpec & AssignProperties_From_VirtualMachineScaleSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec tests if a specific instance of VirtualMachineScaleSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.VirtualMachineScaleSetOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetOperatorSpecGenerator() +var virtualMachineScaleSetOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetOperatorSpecGenerator returns a generator of VirtualMachineScaleSetOperatorSpec instances for property testing. +func VirtualMachineScaleSetOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetOperatorSpecGenerator != nil { + return virtualMachineScaleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetOperatorSpec{}), generators) + + return virtualMachineScaleSetOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetPublicIPAddressConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -6152,6 +6249,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSet_Spec(gens map[string] gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineScaleSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetOperatorSpecGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) gens["ScaleInPolicy"] = gen.PtrOf(ScaleInPolicyGenerator()) diff --git a/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen.go b/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen.go index 2634f4199e6..ad881758a46 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen.go +++ b/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +109,26 @@ func (extension *VirtualMachineScaleSetsExtension) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachineScaleSetsExtension resource func (extension *VirtualMachineScaleSetsExtension) defaultImpl() { extension.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachineScaleSetsExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachineScaleSetsExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSetsExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachineScaleSetsExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSetsExtension{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (extension *VirtualMachineScaleSetsExtension) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (extension *VirtualMachineScaleSetsExtension) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference} + return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference, extension.validateSecretDestinations, extension.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (extension *VirtualMachineScaleSetsExtension) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return extension.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (extension *VirtualMachineScaleSetsExtension) validateConfigMapDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (extension *VirtualMachineScaleSetsExtension) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (extension *VirtualMachineScaleSetsExtension) validateSecretDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (extension *VirtualMachineScaleSetsExtension) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachineScaleSetsExtension) @@ -347,6 +392,10 @@ type VirtualMachineScaleSetsExtension_Spec struct { // update even if the extension configuration has not changed. ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineScaleSetsExtensionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -484,6 +533,8 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": extension.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -617,6 +668,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_From_Vi // ForceUpdateTag extension.ForceUpdateTag = genruntime.ClonePointerToString(source.ForceUpdateTag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetsExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -689,6 +752,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_To_Virt // ForceUpdateTag destination.ForceUpdateTag = genruntime.ClonePointerToString(extension.ForceUpdateTag) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineScaleSetsExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion() @@ -1110,6 +1185,110 @@ func (extension *VirtualMachineScaleSetsExtension_STATUS) AssignProperties_To_Vi return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetsExtensionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec populates our VirtualMachineScaleSetsExtensionOperatorSpec from the provided source VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec populates the provided destination VirtualMachineScaleSetsExtensionOperatorSpec from our VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(destination *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&VirtualMachineScaleSetsExtension{}, &VirtualMachineScaleSetsExtensionList{}) } diff --git a/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen_test.go b/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen_test.go index 53616485cb5..dd10c103027 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen_test.go +++ b/v2/api/compute/v1api20201201/virtual_machine_scale_sets_extension_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension(gens map[st gens["Status"] = VirtualMachineScaleSetsExtension_STATUSGenerator() } +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetsExtensionOperatorSpec to VirtualMachineScaleSetsExtensionOperatorSpec via AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec & AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec tests if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.VirtualMachineScaleSetsExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetsExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator() +var virtualMachineScaleSetsExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator returns a generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing. +func VirtualMachineScaleSetsExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetsExtensionOperatorSpecGenerator != nil { + return virtualMachineScaleSetsExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetsExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtensionOperatorSpec{}), generators) + + return virtualMachineScaleSetsExtensionOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetsExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -365,6 +462,9 @@ func RunJSONSerializationTestForVirtualMachineScaleSetsExtension_Spec(subject Vi var virtualMachineScaleSetsExtension_SpecGenerator gopter.Gen // VirtualMachineScaleSetsExtension_SpecGenerator returns a generator of VirtualMachineScaleSetsExtension_Spec instances for property testing. +// We first initialize virtualMachineScaleSetsExtension_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func VirtualMachineScaleSetsExtension_SpecGenerator() gopter.Gen { if virtualMachineScaleSetsExtension_SpecGenerator != nil { return virtualMachineScaleSetsExtension_SpecGenerator @@ -374,6 +474,12 @@ func VirtualMachineScaleSetsExtension_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) virtualMachineScaleSetsExtension_SpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtension_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) + AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(generators) + virtualMachineScaleSetsExtension_SpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtension_Spec{}), generators) + return virtualMachineScaleSetsExtension_SpecGenerator } @@ -388,3 +494,8 @@ func AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(ge gens["Type"] = gen.PtrOf(gen.AlphaString()) gens["TypeHandlerVersion"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetsExtensionOperatorSpecGenerator()) +} diff --git a/v2/api/compute/v1api20201201/virtual_machine_types_gen.go b/v2/api/compute/v1api20201201/virtual_machine_types_gen.go index 37ce07127d6..1f4ff08b34e 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_types_gen.go +++ b/v2/api/compute/v1api20201201/virtual_machine_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +109,26 @@ func (machine *VirtualMachine) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachine resource func (machine *VirtualMachine) defaultImpl() { machine.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachine{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (machine *VirtualMachine) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachine{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (machine *VirtualMachine) SecretDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachine{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (machine *VirtualMachine) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (machine *VirtualMachine) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){machine.validateResourceReferences, machine.validateOwnerReference} + return []func() (admission.Warnings, error){machine.validateResourceReferences, machine.validateOwnerReference, machine.validateSecretDestinations, machine.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (machine *VirtualMachine) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return machine.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return machine.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return machine.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (machine *VirtualMachine) validateConfigMapDestinations() (admission.Warnings, error) { + if machine.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(machine, nil, machine.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (machine *VirtualMachine) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (machine *VirtualMachine) validateSecretDestinations() (admission.Warnings, error) { + if machine.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(machine, nil, machine.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (machine *VirtualMachine) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachine) @@ -413,6 +458,10 @@ type VirtualMachine_Spec struct { // NetworkProfile: Specifies the network interfaces of the virtual machine. NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineOperatorSpec `json:"operatorSpec,omitempty"` + // OsProfile: Specifies the operating system settings used while creating the virtual machine. Some of the settings cannot // be changed once VM is provisioned. OsProfile *OSProfile `json:"osProfile,omitempty"` @@ -865,6 +914,8 @@ func (machine *VirtualMachine_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "OsProfile": // copying flattened property: if typedInput.Properties != nil { @@ -1183,6 +1234,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_From_VirtualMachine_Spec(so machine.NetworkProfile = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + machine.OperatorSpec = &operatorSpec + } else { + machine.OperatorSpec = nil + } + // OsProfile if source.OsProfile != nil { var osProfile OSProfile @@ -1430,6 +1493,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_To_VirtualMachine_Spec(dest destination.NetworkProfile = nil } + // OperatorSpec + if machine.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineOperatorSpec + err := machine.OperatorSpec.AssignProperties_To_VirtualMachineOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = machine.OriginalVersion() @@ -6814,6 +6889,110 @@ func (view *VirtualMachineInstanceView_STATUS) AssignProperties_To_VirtualMachin return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineOperatorSpec populates our VirtualMachineOperatorSpec from the provided source VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_From_VirtualMachineOperatorSpec(source *storage.VirtualMachineOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineOperatorSpec populates the provided destination VirtualMachineOperatorSpec from our VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_To_VirtualMachineOperatorSpec(destination *storage.VirtualMachineOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Boot Diagnostics is a debugging feature which allows you to view Console Output and Screenshot to diagnose VM status. // You can easily view the output of your console log. // Azure also enables you to see a screenshot of the diff --git a/v2/api/compute/v1api20201201/virtual_machine_types_gen_test.go b/v2/api/compute/v1api20201201/virtual_machine_types_gen_test.go index 0310658fc0d..6183dcc78a1 100644 --- a/v2/api/compute/v1api20201201/virtual_machine_types_gen_test.go +++ b/v2/api/compute/v1api20201201/virtual_machine_types_gen_test.go @@ -9135,6 +9135,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineInstanceView_STATUS(gens map[s gens["VmHealth"] = gen.PtrOf(VirtualMachineHealthStatus_STATUSGenerator()) } +func Test_VirtualMachineOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineOperatorSpec to VirtualMachineOperatorSpec via AssignProperties_To_VirtualMachineOperatorSpec & AssignProperties_From_VirtualMachineOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineOperatorSpec tests if a specific instance of VirtualMachineOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.VirtualMachineOperatorSpec + err := copied.AssignProperties_To_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineOperatorSpec + err = actual.AssignProperties_From_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineOperatorSpec runs a test to see if a specific instance of VirtualMachineOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineOperatorSpecGenerator() +var virtualMachineOperatorSpecGenerator gopter.Gen + +// VirtualMachineOperatorSpecGenerator returns a generator of VirtualMachineOperatorSpec instances for property testing. +func VirtualMachineOperatorSpecGenerator() gopter.Gen { + if virtualMachineOperatorSpecGenerator != nil { + return virtualMachineOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineOperatorSpec{}), generators) + + return virtualMachineOperatorSpecGenerator +} + func Test_VirtualMachinePatchStatus_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -9522,6 +9619,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachine_Spec(gens map[string]gopter.G gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineIdentityGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineOperatorSpecGenerator()) gens["OsProfile"] = gen.PtrOf(OSProfileGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen.go b/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen.go index 77c95d97f24..8deb2762d31 100644 --- a/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen.go +++ b/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +109,26 @@ func (extension *VirtualMachinesExtension) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachinesExtension resource func (extension *VirtualMachinesExtension) defaultImpl() { extension.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachinesExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachinesExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachinesExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachinesExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachinesExtension{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (extension *VirtualMachinesExtension) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (extension *VirtualMachinesExtension) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference} + return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference, extension.validateSecretDestinations, extension.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (extension *VirtualMachinesExtension) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return extension.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (extension *VirtualMachinesExtension) validateConfigMapDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (extension *VirtualMachinesExtension) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (extension *VirtualMachinesExtension) validateSecretDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (extension *VirtualMachinesExtension) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachinesExtension) @@ -353,6 +398,10 @@ type VirtualMachinesExtension_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachinesExtensionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -529,6 +578,8 @@ func (extension *VirtualMachinesExtension_Spec) PopulateFromARM(owner genruntime extension.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": extension.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -677,6 +728,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_From_VirtualMac // Location extension.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachinesExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -764,6 +827,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_To_VirtualMachi // Location destination.Location = genruntime.ClonePointerToString(extension.Location) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachinesExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion() @@ -1659,6 +1734,110 @@ func (view *VirtualMachineExtensionInstanceView_STATUS) AssignProperties_To_Virt return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachinesExtensionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachinesExtensionOperatorSpec populates our VirtualMachinesExtensionOperatorSpec from the provided source VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source *storage.VirtualMachinesExtensionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachinesExtensionOperatorSpec populates the provided destination VirtualMachinesExtensionOperatorSpec from our VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_To_VirtualMachinesExtensionOperatorSpec(destination *storage.VirtualMachinesExtensionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Instance view status. type InstanceViewStatus struct { // Code: The status code. diff --git a/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen_test.go b/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen_test.go index 990ba3c873b..8ba69d1f134 100644 --- a/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen_test.go +++ b/v2/api/compute/v1api20201201/virtual_machines_extension_types_gen_test.go @@ -512,6 +512,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachinesExtension(gens map[string]gop gens["Status"] = VirtualMachinesExtension_STATUSGenerator() } +func Test_VirtualMachinesExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachinesExtensionOperatorSpec to VirtualMachinesExtensionOperatorSpec via AssignProperties_To_VirtualMachinesExtensionOperatorSpec & AssignProperties_From_VirtualMachinesExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec tests if a specific instance of VirtualMachinesExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20201201s.VirtualMachinesExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachinesExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachinesExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachinesExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachinesExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachinesExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachinesExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachinesExtensionOperatorSpecGenerator() +var virtualMachinesExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachinesExtensionOperatorSpecGenerator returns a generator of VirtualMachinesExtensionOperatorSpec instances for property testing. +func VirtualMachinesExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachinesExtensionOperatorSpecGenerator != nil { + return virtualMachinesExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachinesExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachinesExtensionOperatorSpec{}), generators) + + return virtualMachinesExtensionOperatorSpecGenerator +} + func Test_VirtualMachinesExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -767,4 +864,5 @@ func AddIndependentPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[s // AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[string]gopter.Gen) { gens["InstanceView"] = gen.PtrOf(VirtualMachineExtensionInstanceViewGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachinesExtensionOperatorSpecGenerator()) } diff --git a/v2/api/compute/v1api20201201/zz_generated.deepcopy.go b/v2/api/compute/v1api20201201/zz_generated.deepcopy.go index 728f294c8a4..625143f3c44 100644 --- a/v2/api/compute/v1api20201201/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20201201/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20201201 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -3306,6 +3307,43 @@ func (in *VirtualMachineList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineOperatorSpec) DeepCopyInto(out *VirtualMachineOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineOperatorSpec. +func (in *VirtualMachineOperatorSpec) DeepCopy() *VirtualMachineOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinePatchStatus_STATUS) DeepCopyInto(out *VirtualMachinePatchStatus_STATUS) { *out = *in @@ -4495,6 +4533,43 @@ func (in *VirtualMachineScaleSetOSProfile_STATUS) DeepCopy() *VirtualMachineScal return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetOperatorSpec. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopy() *VirtualMachineScaleSetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetPublicIPAddressConfiguration) DeepCopyInto(out *VirtualMachineScaleSetPublicIPAddressConfiguration) { *out = *in @@ -5020,6 +5095,11 @@ func (in *VirtualMachineScaleSet_Spec) DeepCopyInto(out *VirtualMachineScaleSet_ *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestrationMode != nil { in, out := &in.OrchestrationMode, &out.OrchestrationMode *out = new(OrchestrationMode) @@ -5163,6 +5243,43 @@ func (in *VirtualMachineScaleSetsExtensionList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetsExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetsExtensionOperatorSpec. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopy() *VirtualMachineScaleSetsExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetsExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetsExtension_STATUS) DeepCopyInto(out *VirtualMachineScaleSetsExtension_STATUS) { *out = *in @@ -5265,6 +5382,11 @@ func (in *VirtualMachineScaleSetsExtension_Spec) DeepCopyInto(out *VirtualMachin *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetsExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5568,6 +5690,11 @@ func (in *VirtualMachine_Spec) DeepCopyInto(out *VirtualMachine_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsProfile != nil { in, out := &in.OsProfile, &out.OsProfile *out = new(OSProfile) @@ -5696,6 +5823,43 @@ func (in *VirtualMachinesExtensionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopyInto(out *VirtualMachinesExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachinesExtensionOperatorSpec. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopy() *VirtualMachinesExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachinesExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinesExtension_STATUS) DeepCopyInto(out *VirtualMachinesExtension_STATUS) { *out = *in @@ -5820,6 +5984,11 @@ func (in *VirtualMachinesExtension_Spec) DeepCopyInto(out *VirtualMachinesExtens *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachinesExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20210701/image_types_gen.go b/v2/api/compute/v1api20210701/image_types_gen.go index 6a3af3769b3..c04548e3372 100644 --- a/v2/api/compute/v1api20210701/image_types_gen.go +++ b/v2/api/compute/v1api20210701/image_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (image *Image) defaultAzureName() { // defaultImpl applies the code generated defaults to the Image resource func (image *Image) defaultImpl() { image.defaultAzureName() } +var _ configmaps.Exporter = &Image{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (image *Image) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Image{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (image *Image) SecretDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Image{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (image *Image) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (image *Image) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){image.validateResourceReferences, image.validateOwnerReference} + return []func() (admission.Warnings, error){image.validateResourceReferences, image.validateOwnerReference, image.validateSecretDestinations, image.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (image *Image) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return image.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return image.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return image.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (image *Image) validateConfigMapDestinations() (admission.Warnings, error) { + if image.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(image, nil, image.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (image *Image) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (image *Image) validateSecretDestinations() (admission.Warnings, error) { + if image.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(image, nil, image.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (image *Image) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Image) @@ -351,6 +396,10 @@ type Image_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ImageOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -477,6 +526,8 @@ func (image *Image_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc image.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": image.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -603,6 +654,18 @@ func (image *Image_Spec) AssignProperties_From_Image_Spec(source *storage.Image_ // Location image.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ImageOperatorSpec + err := operatorSpec.AssignProperties_From_ImageOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ImageOperatorSpec() to populate field OperatorSpec") + } + image.OperatorSpec = &operatorSpec + } else { + image.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -673,6 +736,18 @@ func (image *Image_Spec) AssignProperties_To_Image_Spec(destination *storage.Ima // Location destination.Location = genruntime.ClonePointerToString(image.Location) + // OperatorSpec + if image.OperatorSpec != nil { + var operatorSpec storage.ImageOperatorSpec + err := image.OperatorSpec.AssignProperties_To_ImageOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ImageOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = image.OriginalVersion() @@ -1311,6 +1386,110 @@ var hyperVGenerationType_STATUS_Values = map[string]HyperVGenerationType_STATUS{ "v2": HyperVGenerationType_STATUS_V2, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ImageOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ImageOperatorSpec populates our ImageOperatorSpec from the provided source ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_From_ImageOperatorSpec(source *storage.ImageOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ImageOperatorSpec populates the provided destination ImageOperatorSpec from our ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_To_ImageOperatorSpec(destination *storage.ImageOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Describes a storage profile. type ImageStorageProfile struct { // DataDisks: Specifies the parameters that are used to add a data disk to a virtual machine. diff --git a/v2/api/compute/v1api20210701/image_types_gen_test.go b/v2/api/compute/v1api20210701/image_types_gen_test.go index 6b90f6460d2..480418f3b9a 100644 --- a/v2/api/compute/v1api20210701/image_types_gen_test.go +++ b/v2/api/compute/v1api20210701/image_types_gen_test.go @@ -887,6 +887,102 @@ func AddRelatedPropertyGeneratorsForImageOSDisk_STATUS(gens map[string]gopter.Ge gens["Snapshot"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_ImageOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ImageOperatorSpec to ImageOperatorSpec via AssignProperties_To_ImageOperatorSpec & AssignProperties_From_ImageOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForImageOperatorSpec tests if a specific instance of ImageOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210701s.ImageOperatorSpec + err := copied.AssignProperties_To_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ImageOperatorSpec + err = actual.AssignProperties_From_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ImageOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ImageOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForImageOperatorSpec runs a test to see if a specific instance of ImageOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ImageOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ImageOperatorSpec instances for property testing - lazily instantiated by ImageOperatorSpecGenerator() +var imageOperatorSpecGenerator gopter.Gen + +// ImageOperatorSpecGenerator returns a generator of ImageOperatorSpec instances for property testing. +func ImageOperatorSpecGenerator() gopter.Gen { + if imageOperatorSpecGenerator != nil { + return imageOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + imageOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ImageOperatorSpec{}), generators) + + return imageOperatorSpecGenerator +} + func Test_ImageStorageProfile_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1368,6 +1464,7 @@ func AddIndependentPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForImage_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ImageOperatorSpecGenerator()) gens["SourceVirtualMachine"] = gen.PtrOf(SubResourceGenerator()) gens["StorageProfile"] = gen.PtrOf(ImageStorageProfileGenerator()) } diff --git a/v2/api/compute/v1api20210701/storage/image_types_gen.go b/v2/api/compute/v1api20210701/storage/image_types_gen.go index 219f6ec335f..b45bc234c32 100644 --- a/v2/api/compute/v1api20210701/storage/image_types_gen.go +++ b/v2/api/compute/v1api20210701/storage/image_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220301/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (image *Image) ConvertTo(hub conversion.Hub) error { return image.AssignProperties_To_Image(destination) } +var _ configmaps.Exporter = &Image{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (image *Image) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Image{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (image *Image) SecretDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Image{} // AzureName returns the Azure name of the resource @@ -241,11 +264,12 @@ type augmentConversionForImage interface { type Image_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - HyperVGeneration *string `json:"hyperVGeneration,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + HyperVGeneration *string `json:"hyperVGeneration,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *ImageOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -334,6 +358,18 @@ func (image *Image_Spec) AssignProperties_From_Image_Spec(source *storage.Image_ // Location image.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ImageOperatorSpec + err := operatorSpec.AssignProperties_From_ImageOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ImageOperatorSpec() to populate field OperatorSpec") + } + image.OperatorSpec = &operatorSpec + } else { + image.OperatorSpec = nil + } + // OriginalVersion image.OriginalVersion = source.OriginalVersion @@ -418,6 +454,18 @@ func (image *Image_Spec) AssignProperties_To_Image_Spec(destination *storage.Ima // Location destination.Location = genruntime.ClonePointerToString(image.Location) + // OperatorSpec + if image.OperatorSpec != nil { + var operatorSpec storage.ImageOperatorSpec + err := image.OperatorSpec.AssignProperties_To_ImageOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ImageOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = image.OriginalVersion @@ -864,6 +912,136 @@ func (location *ExtendedLocation_STATUS) AssignProperties_To_ExtendedLocation_ST return nil } +// Storage version of v1api20210701.ImageOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ImageOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ImageOperatorSpec populates our ImageOperatorSpec from the provided source ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_From_ImageOperatorSpec(source *storage.ImageOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForImageOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForImageOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ImageOperatorSpec populates the provided destination ImageOperatorSpec from our ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_To_ImageOperatorSpec(destination *storage.ImageOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForImageOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForImageOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210701.ImageStorageProfile // Describes a storage profile. type ImageStorageProfile struct { @@ -1280,6 +1458,11 @@ type augmentConversionForExtendedLocation_STATUS interface { AssignPropertiesTo(dst *storage.ExtendedLocation_STATUS) error } +type augmentConversionForImageOperatorSpec interface { + AssignPropertiesFrom(src *storage.ImageOperatorSpec) error + AssignPropertiesTo(dst *storage.ImageOperatorSpec) error +} + type augmentConversionForImageStorageProfile interface { AssignPropertiesFrom(src *storage.ImageStorageProfile) error AssignPropertiesTo(dst *storage.ImageStorageProfile) error diff --git a/v2/api/compute/v1api20210701/storage/image_types_gen_test.go b/v2/api/compute/v1api20210701/storage/image_types_gen_test.go index ab7673bb78b..c2dc7fcea91 100644 --- a/v2/api/compute/v1api20210701/storage/image_types_gen_test.go +++ b/v2/api/compute/v1api20210701/storage/image_types_gen_test.go @@ -862,6 +862,102 @@ func AddRelatedPropertyGeneratorsForImageOSDisk_STATUS(gens map[string]gopter.Ge gens["Snapshot"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_ImageOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ImageOperatorSpec to ImageOperatorSpec via AssignProperties_To_ImageOperatorSpec & AssignProperties_From_ImageOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForImageOperatorSpec tests if a specific instance of ImageOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ImageOperatorSpec + err := copied.AssignProperties_To_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ImageOperatorSpec + err = actual.AssignProperties_From_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ImageOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ImageOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForImageOperatorSpec runs a test to see if a specific instance of ImageOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ImageOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ImageOperatorSpec instances for property testing - lazily instantiated by ImageOperatorSpecGenerator() +var imageOperatorSpecGenerator gopter.Gen + +// ImageOperatorSpecGenerator returns a generator of ImageOperatorSpec instances for property testing. +func ImageOperatorSpecGenerator() gopter.Gen { + if imageOperatorSpecGenerator != nil { + return imageOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + imageOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ImageOperatorSpec{}), generators) + + return imageOperatorSpecGenerator +} + func Test_ImageStorageProfile_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1344,6 +1440,7 @@ func AddIndependentPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForImage_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ImageOperatorSpecGenerator()) gens["SourceVirtualMachine"] = gen.PtrOf(SubResourceGenerator()) gens["StorageProfile"] = gen.PtrOf(ImageStorageProfileGenerator()) } diff --git a/v2/api/compute/v1api20210701/storage/structure.txt b/v2/api/compute/v1api20210701/storage/structure.txt index a3191cbb128..fe3297d3821 100644 --- a/v2/api/compute/v1api20210701/storage/structure.txt +++ b/v2/api/compute/v1api20210701/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-07-01" Image: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (3 properties) │ │ ├── Name: *string @@ -13,6 +13,10 @@ Image: Resource │ │ └── Type: *string │ ├── HyperVGeneration: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -116,6 +120,7 @@ augmentConversionForImageDataDisk: Interface augmentConversionForImageDataDisk_STATUS: Interface augmentConversionForImageOSDisk: Interface augmentConversionForImageOSDisk_STATUS: Interface +augmentConversionForImageOperatorSpec: Interface augmentConversionForImageStorageProfile: Interface augmentConversionForImageStorageProfile_STATUS: Interface augmentConversionForImage_STATUS: Interface diff --git a/v2/api/compute/v1api20210701/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20210701/storage/zz_generated.deepcopy.go index 8290bb00a97..670c5b41681 100644 --- a/v2/api/compute/v1api20210701/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20210701/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -396,6 +397,50 @@ func (in *ImageOSDisk_STATUS) DeepCopy() *ImageOSDisk_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageOperatorSpec) DeepCopyInto(out *ImageOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageOperatorSpec. +func (in *ImageOperatorSpec) DeepCopy() *ImageOperatorSpec { + if in == nil { + return nil + } + out := new(ImageOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageStorageProfile) DeepCopyInto(out *ImageStorageProfile) { *out = *in @@ -573,6 +618,11 @@ func (in *Image_Spec) DeepCopyInto(out *Image_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ImageOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20210701/structure.txt b/v2/api/compute/v1api20210701/structure.txt index 693850fb445..ce8da406080 100644 --- a/v2/api/compute/v1api20210701/structure.txt +++ b/v2/api/compute/v1api20210701/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-07-01" Image: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (2 properties) │ │ ├── Name: *string @@ -15,6 +15,9 @@ Image: Resource │ │ ├── "V1" │ │ └── "V2" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── SourceVirtualMachine: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference diff --git a/v2/api/compute/v1api20210701/zz_generated.deepcopy.go b/v2/api/compute/v1api20210701/zz_generated.deepcopy.go index c6b0440b8de..16f31cbdb84 100644 --- a/v2/api/compute/v1api20210701/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20210701/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210701 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -354,6 +355,43 @@ func (in *ImageOSDisk_STATUS) DeepCopy() *ImageOSDisk_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageOperatorSpec) DeepCopyInto(out *ImageOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageOperatorSpec. +func (in *ImageOperatorSpec) DeepCopy() *ImageOperatorSpec { + if in == nil { + return nil + } + out := new(ImageOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageStorageProfile) DeepCopyInto(out *ImageStorageProfile) { *out = *in @@ -510,6 +548,11 @@ func (in *Image_Spec) DeepCopyInto(out *Image_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ImageOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20220301/image_types_gen.go b/v2/api/compute/v1api20220301/image_types_gen.go index b832d3f9b45..ef5eec0ceb9 100644 --- a/v2/api/compute/v1api20220301/image_types_gen.go +++ b/v2/api/compute/v1api20220301/image_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (image *Image) defaultAzureName() { // defaultImpl applies the code generated defaults to the Image resource func (image *Image) defaultImpl() { image.defaultAzureName() } +var _ configmaps.Exporter = &Image{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (image *Image) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Image{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (image *Image) SecretDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Image{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (image *Image) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (image *Image) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){image.validateResourceReferences, image.validateOwnerReference} + return []func() (admission.Warnings, error){image.validateResourceReferences, image.validateOwnerReference, image.validateSecretDestinations, image.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (image *Image) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return image.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return image.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return image.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (image *Image) validateConfigMapDestinations() (admission.Warnings, error) { + if image.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(image, nil, image.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (image *Image) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (image *Image) validateSecretDestinations() (admission.Warnings, error) { + if image.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(image, nil, image.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (image *Image) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Image) @@ -348,6 +393,10 @@ type Image_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ImageOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -474,6 +523,8 @@ func (image *Image_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc image.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": image.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -600,6 +651,18 @@ func (image *Image_Spec) AssignProperties_From_Image_Spec(source *storage.Image_ // Location image.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ImageOperatorSpec + err := operatorSpec.AssignProperties_From_ImageOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ImageOperatorSpec() to populate field OperatorSpec") + } + image.OperatorSpec = &operatorSpec + } else { + image.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -670,6 +733,18 @@ func (image *Image_Spec) AssignProperties_To_Image_Spec(destination *storage.Ima // Location destination.Location = genruntime.ClonePointerToString(image.Location) + // OperatorSpec + if image.OperatorSpec != nil { + var operatorSpec storage.ImageOperatorSpec + err := image.OperatorSpec.AssignProperties_To_ImageOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ImageOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = image.OriginalVersion() @@ -1383,6 +1458,110 @@ var hyperVGenerationType_STATUS_Values = map[string]HyperVGenerationType_STATUS{ "v2": HyperVGenerationType_STATUS_V2, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ImageOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ImageOperatorSpec populates our ImageOperatorSpec from the provided source ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_From_ImageOperatorSpec(source *storage.ImageOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ImageOperatorSpec populates the provided destination ImageOperatorSpec from our ImageOperatorSpec +func (operator *ImageOperatorSpec) AssignProperties_To_ImageOperatorSpec(destination *storage.ImageOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Describes a storage profile. type ImageStorageProfile struct { // DataDisks: Specifies the parameters that are used to add a data disk to a virtual machine. diff --git a/v2/api/compute/v1api20220301/image_types_gen_test.go b/v2/api/compute/v1api20220301/image_types_gen_test.go index ef104df600f..c73537a0096 100644 --- a/v2/api/compute/v1api20220301/image_types_gen_test.go +++ b/v2/api/compute/v1api20220301/image_types_gen_test.go @@ -890,6 +890,102 @@ func AddRelatedPropertyGeneratorsForImageOSDisk_STATUS(gens map[string]gopter.Ge gens["Snapshot"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_ImageOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ImageOperatorSpec to ImageOperatorSpec via AssignProperties_To_ImageOperatorSpec & AssignProperties_From_ImageOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForImageOperatorSpec tests if a specific instance of ImageOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ImageOperatorSpec + err := copied.AssignProperties_To_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ImageOperatorSpec + err = actual.AssignProperties_From_ImageOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ImageOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ImageOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForImageOperatorSpec runs a test to see if a specific instance of ImageOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ImageOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ImageOperatorSpec instances for property testing - lazily instantiated by ImageOperatorSpecGenerator() +var imageOperatorSpecGenerator gopter.Gen + +// ImageOperatorSpecGenerator returns a generator of ImageOperatorSpec instances for property testing. +func ImageOperatorSpecGenerator() gopter.Gen { + if imageOperatorSpecGenerator != nil { + return imageOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + imageOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ImageOperatorSpec{}), generators) + + return imageOperatorSpecGenerator +} + func Test_ImageStorageProfile_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1371,6 +1467,7 @@ func AddIndependentPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForImage_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ImageOperatorSpecGenerator()) gens["SourceVirtualMachine"] = gen.PtrOf(SubResourceGenerator()) gens["StorageProfile"] = gen.PtrOf(ImageStorageProfileGenerator()) } diff --git a/v2/api/compute/v1api20220301/storage/image_types_gen.go b/v2/api/compute/v1api20220301/storage/image_types_gen.go index 2c5cf82ce12..fd7061a583a 100644 --- a/v2/api/compute/v1api20220301/storage/image_types_gen.go +++ b/v2/api/compute/v1api20220301/storage/image_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20240302/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (image *Image) SetConditions(conditions conditions.Conditions) { image.Status.Conditions = conditions } +var _ configmaps.Exporter = &Image{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (image *Image) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Image{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (image *Image) SecretDestinationExpressions() []*core.DestinationExpression { + if image.Spec.OperatorSpec == nil { + return nil + } + return image.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Image{} // AzureName returns the Azure name of the resource @@ -149,11 +172,12 @@ const APIVersion_Value = APIVersion("2022-03-01") type Image_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - HyperVGeneration *string `json:"hyperVGeneration,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + HyperVGeneration *string `json:"hyperVGeneration,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *ImageOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -364,6 +388,14 @@ func (location *ExtendedLocation_STATUS) AssignProperties_To_ExtendedLocation_ST return nil } +// Storage version of v1api20220301.ImageOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ImageOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.ImageStorageProfile // Describes a storage profile. type ImageStorageProfile struct { diff --git a/v2/api/compute/v1api20220301/storage/image_types_gen_test.go b/v2/api/compute/v1api20220301/storage/image_types_gen_test.go index 09c2640e368..1a8f5ba3b8a 100644 --- a/v2/api/compute/v1api20220301/storage/image_types_gen_test.go +++ b/v2/api/compute/v1api20220301/storage/image_types_gen_test.go @@ -609,6 +609,60 @@ func AddRelatedPropertyGeneratorsForImageOSDisk_STATUS(gens map[string]gopter.Ge gens["Snapshot"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_ImageOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ImageOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForImageOperatorSpec, ImageOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForImageOperatorSpec runs a test to see if a specific instance of ImageOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForImageOperatorSpec(subject ImageOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ImageOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ImageOperatorSpec instances for property testing - lazily instantiated by ImageOperatorSpecGenerator() +var imageOperatorSpecGenerator gopter.Gen + +// ImageOperatorSpecGenerator returns a generator of ImageOperatorSpec instances for property testing. +func ImageOperatorSpecGenerator() gopter.Gen { + if imageOperatorSpecGenerator != nil { + return imageOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + imageOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ImageOperatorSpec{}), generators) + + return imageOperatorSpecGenerator +} + func Test_ImageStorageProfile_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -923,6 +977,7 @@ func AddIndependentPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForImage_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForImage_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ImageOperatorSpecGenerator()) gens["SourceVirtualMachine"] = gen.PtrOf(SubResourceGenerator()) gens["StorageProfile"] = gen.PtrOf(ImageStorageProfileGenerator()) } diff --git a/v2/api/compute/v1api20220301/storage/structure.txt b/v2/api/compute/v1api20220301/storage/structure.txt index 78055e31af6..fe456dea381 100644 --- a/v2/api/compute/v1api20220301/storage/structure.txt +++ b/v2/api/compute/v1api20220301/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-03-01" Image: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (3 properties) │ │ ├── Name: *string @@ -13,6 +13,10 @@ Image: Resource │ │ └── Type: *string │ ├── HyperVGeneration: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -111,7 +115,7 @@ Image: Resource └── Type: *string VirtualMachine: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (32 properties) +├── Spec: Object (33 properties) │ ├── AdditionalCapabilities: *Object (3 properties) │ │ ├── HibernationEnabled: *bool │ │ ├── PropertyBag: genruntime.PropertyBag @@ -234,6 +238,10 @@ VirtualMachine: Resource │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── Reference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsProfile: *Object (10 properties) │ │ ├── AdminPassword: *genruntime.SecretReference @@ -940,7 +948,7 @@ VirtualMachine: Resource └── Zones: string[] VirtualMachineScaleSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (25 properties) +├── Spec: Object (26 properties) │ ├── AdditionalCapabilities: *Object (3 properties) │ │ ├── HibernationEnabled: *bool │ │ ├── PropertyBag: genruntime.PropertyBag @@ -966,6 +974,10 @@ VirtualMachineScaleSet: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestrationMode: *string │ ├── OriginalVersion: string │ ├── Overprovision: *bool @@ -1609,11 +1621,15 @@ VirtualMachineScaleSet: Resource └── Zones: string[] VirtualMachineScaleSetsExtension: Resource ├── Owner: compute/v1api20220301.VirtualMachineScaleSet -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool │ ├── ForceUpdateTag: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1654,7 +1670,7 @@ VirtualMachineScaleSetsExtension: Resource └── TypeHandlerVersion: *string VirtualMachinesExtension: Resource ├── Owner: compute/v1api20220301.VirtualMachine -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool @@ -1679,6 +1695,10 @@ VirtualMachinesExtension: Resource │ │ ├── Type: *string │ │ └── TypeHandlerVersion: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen.go b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen.go index dd64dedd254..4a980d6fc2a 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (scaleSet *VirtualMachineScaleSet) SetConditions(conditions conditions.Cond scaleSet.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualMachineScaleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (scaleSet *VirtualMachineScaleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (scaleSet *VirtualMachineScaleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSet{} // AzureName returns the Azure name of the resource @@ -146,15 +169,16 @@ type VirtualMachineScaleSet_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DoNotRunExtensionsOnOverprovisionedVMs *bool `json:"doNotRunExtensionsOnOverprovisionedVMs,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - HostGroup *SubResource `json:"hostGroup,omitempty"` - Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"` - Location *string `json:"location,omitempty"` - OrchestrationMode *string `json:"orchestrationMode,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - Overprovision *bool `json:"overprovision,omitempty"` + AzureName string `json:"azureName,omitempty"` + DoNotRunExtensionsOnOverprovisionedVMs *bool `json:"doNotRunExtensionsOnOverprovisionedVMs,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + HostGroup *SubResource `json:"hostGroup,omitempty"` + Identity *VirtualMachineScaleSetIdentity `json:"identity,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VirtualMachineScaleSetOperatorSpec `json:"operatorSpec,omitempty"` + OrchestrationMode *string `json:"orchestrationMode,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + Overprovision *bool `json:"overprovision,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -362,6 +386,14 @@ type VirtualMachineScaleSetIdentity_STATUS struct { UserAssignedIdentities map[string]VirtualMachineScaleSetIdentity_UserAssignedIdentities_STATUS `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20220301.VirtualMachineScaleSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.VirtualMachineScaleSetVMProfile // Describes a virtual machine scale set virtual machine profile. type VirtualMachineScaleSetVMProfile struct { diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen_test.go b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen_test.go index 685f1ceef82..5c638530a9f 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen_test.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_set_types_gen_test.go @@ -3130,6 +3130,61 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetOSProfile_STATUS(gens gens["WindowsConfiguration"] = gen.PtrOf(WindowsConfiguration_STATUSGenerator()) } +func Test_VirtualMachineScaleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetOperatorSpecGenerator() +var virtualMachineScaleSetOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetOperatorSpecGenerator returns a generator of VirtualMachineScaleSetOperatorSpec instances for property testing. +func VirtualMachineScaleSetOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetOperatorSpecGenerator != nil { + return virtualMachineScaleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetOperatorSpec{}), generators) + + return virtualMachineScaleSetOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetPublicIPAddressConfiguration_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3907,6 +3962,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSet_Spec(gens map[string] gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineScaleSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetOperatorSpecGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) gens["ScaleInPolicy"] = gen.PtrOf(ScaleInPolicyGenerator()) diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen.go b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen.go index d625ba94b4f..e7876b97996 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (extension *VirtualMachineScaleSetsExtension) SetConditions(conditions cond extension.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualMachineScaleSetsExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachineScaleSetsExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSetsExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachineScaleSetsExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachineScaleSetsExtension{} // AzureName returns the Azure name of the resource @@ -145,10 +168,11 @@ type VirtualMachineScaleSetsExtension_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` - ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` + ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + OperatorSpec *VirtualMachineScaleSetsExtensionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -242,6 +266,14 @@ type KeyVaultSecretReference_STATUS struct { SourceVault *SubResource_STATUS `json:"sourceVault,omitempty"` } +// Storage version of v1api20220301.VirtualMachineScaleSetsExtensionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetsExtensionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&VirtualMachineScaleSetsExtension{}, &VirtualMachineScaleSetsExtensionList{}) } diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen_test.go b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen_test.go index fd3592b7ade..0c702ad83ce 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen_test.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_scale_sets_extension_types_gen_test.go @@ -229,6 +229,61 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension(gens map[st gens["Status"] = VirtualMachineScaleSetsExtension_STATUSGenerator() } +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetsExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator() +var virtualMachineScaleSetsExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator returns a generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing. +func VirtualMachineScaleSetsExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetsExtensionOperatorSpecGenerator != nil { + return virtualMachineScaleSetsExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetsExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtensionOperatorSpec{}), generators) + + return virtualMachineScaleSetsExtensionOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetsExtension_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -396,5 +451,6 @@ func AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(ge // AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetsExtensionOperatorSpecGenerator()) gens["ProtectedSettingsFromKeyVault"] = gen.PtrOf(KeyVaultSecretReferenceGenerator()) } diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen.go b/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen.go index 3e4c8a21e57..c7959b67607 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20220702/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -46,6 +49,26 @@ func (machine *VirtualMachine) SetConditions(conditions conditions.Conditions) { machine.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualMachine{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (machine *VirtualMachine) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachine{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (machine *VirtualMachine) SecretDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachine{} // AzureName returns the Azure name of the resource @@ -162,6 +185,7 @@ type VirtualMachine_Spec struct { LicenseType *string `json:"licenseType,omitempty"` Location *string `json:"location,omitempty"` NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + OperatorSpec *VirtualMachineOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OsProfile *OSProfile `json:"osProfile,omitempty"` @@ -544,6 +568,14 @@ type VirtualMachineInstanceView_STATUS struct { VmHealth *VirtualMachineHealthStatus_STATUS `json:"vmHealth,omitempty"` } +// Storage version of v1api20220301.VirtualMachineOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.BootDiagnostics // Boot Diagnostics is a debugging feature which allows you to view Console Output and Screenshot to diagnose VM status. // You can easily view the output of your console log. diff --git a/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen_test.go b/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen_test.go index 61be5693062..3e37176cd75 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen_test.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machine_types_gen_test.go @@ -7116,6 +7116,61 @@ func AddRelatedPropertyGeneratorsForVirtualMachineNetworkInterfaceIPConfiguratio gens["Subnet"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_VirtualMachineOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineOperatorSpec runs a test to see if a specific instance of VirtualMachineOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineOperatorSpecGenerator() +var virtualMachineOperatorSpecGenerator gopter.Gen + +// VirtualMachineOperatorSpecGenerator returns a generator of VirtualMachineOperatorSpec instances for property testing. +func VirtualMachineOperatorSpecGenerator() gopter.Gen { + if virtualMachineOperatorSpecGenerator != nil { + return virtualMachineOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineOperatorSpec{}), generators) + + return virtualMachineOperatorSpecGenerator +} + func Test_VirtualMachinePatchStatus_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -7672,6 +7727,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachine_Spec(gens map[string]gopter.G gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineIdentityGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineOperatorSpecGenerator()) gens["OsProfile"] = gen.PtrOf(OSProfileGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen.go b/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen.go index 9611eb51d2c..346f80caabb 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (extension *VirtualMachinesExtension) SetConditions(conditions conditions.C extension.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualMachinesExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachinesExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachinesExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachinesExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualMachinesExtension{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type VirtualMachinesExtension_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` - ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` - InstanceView *VirtualMachineExtensionInstanceView `json:"instanceView,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnableAutomaticUpgrade *bool `json:"enableAutomaticUpgrade,omitempty"` + ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + InstanceView *VirtualMachineExtensionInstanceView `json:"instanceView,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VirtualMachinesExtensionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -252,6 +276,14 @@ type VirtualMachineExtensionInstanceView_STATUS struct { TypeHandlerVersion *string `json:"typeHandlerVersion,omitempty"` } +// Storage version of v1api20220301.VirtualMachinesExtensionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachinesExtensionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.InstanceViewStatus // Instance view status. type InstanceViewStatus struct { diff --git a/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen_test.go b/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen_test.go index c679d68f295..e594b7e79d1 100644 --- a/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen_test.go +++ b/v2/api/compute/v1api20220301/storage/virtual_machines_extension_types_gen_test.go @@ -299,6 +299,61 @@ func AddRelatedPropertyGeneratorsForVirtualMachinesExtension(gens map[string]gop gens["Status"] = VirtualMachinesExtension_STATUSGenerator() } +func Test_VirtualMachinesExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachinesExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachinesExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachinesExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachinesExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachinesExtensionOperatorSpecGenerator() +var virtualMachinesExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachinesExtensionOperatorSpecGenerator returns a generator of VirtualMachinesExtensionOperatorSpec instances for property testing. +func VirtualMachinesExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachinesExtensionOperatorSpecGenerator != nil { + return virtualMachinesExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachinesExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachinesExtensionOperatorSpec{}), generators) + + return virtualMachinesExtensionOperatorSpecGenerator +} + func Test_VirtualMachinesExtension_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -474,5 +529,6 @@ func AddIndependentPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[s // AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[string]gopter.Gen) { gens["InstanceView"] = gen.PtrOf(VirtualMachineExtensionInstanceViewGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachinesExtensionOperatorSpecGenerator()) gens["ProtectedSettingsFromKeyVault"] = gen.PtrOf(KeyVaultSecretReferenceGenerator()) } diff --git a/v2/api/compute/v1api20220301/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20220301/storage/zz_generated.deepcopy.go index bbdf89ec14a..a2c82ba8107 100644 --- a/v2/api/compute/v1api20220301/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20220301/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1633,6 +1634,50 @@ func (in *ImageOSDisk_STATUS) DeepCopy() *ImageOSDisk_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageOperatorSpec) DeepCopyInto(out *ImageOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageOperatorSpec. +func (in *ImageOperatorSpec) DeepCopy() *ImageOperatorSpec { + if in == nil { + return nil + } + out := new(ImageOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageReference) DeepCopyInto(out *ImageReference) { *out = *in @@ -1929,6 +1974,11 @@ func (in *Image_Spec) DeepCopyInto(out *Image_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ImageOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5662,6 +5712,50 @@ func (in *VirtualMachineNetworkInterfaceIPConfiguration_STATUS) DeepCopy() *Virt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineOperatorSpec) DeepCopyInto(out *VirtualMachineOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineOperatorSpec. +func (in *VirtualMachineOperatorSpec) DeepCopy() *VirtualMachineOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinePatchStatus_STATUS) DeepCopyInto(out *VirtualMachinePatchStatus_STATUS) { *out = *in @@ -7361,6 +7455,50 @@ func (in *VirtualMachineScaleSetOSProfile_STATUS) DeepCopy() *VirtualMachineScal return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetOperatorSpec. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopy() *VirtualMachineScaleSetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetPublicIPAddressConfiguration) DeepCopyInto(out *VirtualMachineScaleSetPublicIPAddressConfiguration) { *out = *in @@ -8019,6 +8157,11 @@ func (in *VirtualMachineScaleSet_Spec) DeepCopyInto(out *VirtualMachineScaleSet_ *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestrationMode != nil { in, out := &in.OrchestrationMode, &out.OrchestrationMode *out = new(string) @@ -8174,6 +8317,50 @@ func (in *VirtualMachineScaleSetsExtensionList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetsExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetsExtensionOperatorSpec. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopy() *VirtualMachineScaleSetsExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetsExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetsExtension_STATUS) DeepCopyInto(out *VirtualMachineScaleSetsExtension_STATUS) { *out = *in @@ -8293,6 +8480,11 @@ func (in *VirtualMachineScaleSetsExtension_Spec) DeepCopyInto(out *VirtualMachin *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetsExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -8655,6 +8847,11 @@ func (in *VirtualMachine_Spec) DeepCopyInto(out *VirtualMachine_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsProfile != nil { in, out := &in.OsProfile, &out.OsProfile *out = new(OSProfile) @@ -8800,6 +8997,50 @@ func (in *VirtualMachinesExtensionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopyInto(out *VirtualMachinesExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachinesExtensionOperatorSpec. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopy() *VirtualMachinesExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachinesExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinesExtension_STATUS) DeepCopyInto(out *VirtualMachinesExtension_STATUS) { *out = *in @@ -8941,6 +9182,11 @@ func (in *VirtualMachinesExtension_Spec) DeepCopyInto(out *VirtualMachinesExtens *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachinesExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20220301/structure.txt b/v2/api/compute/v1api20220301/structure.txt index 1afb04eaaf5..1a86e53330b 100644 --- a/v2/api/compute/v1api20220301/structure.txt +++ b/v2/api/compute/v1api20220301/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-03-01" Image: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (2 properties) │ │ ├── Name: *string @@ -15,6 +15,9 @@ Image: Resource │ │ ├── "V1" │ │ └── "V2" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── SourceVirtualMachine: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -140,7 +143,7 @@ Image: Resource └── Type: *string VirtualMachine: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (30 properties) +├── Spec: Object (31 properties) │ ├── AdditionalCapabilities: *Object (2 properties) │ │ ├── HibernationEnabled: *bool │ │ └── UltraSSDEnabled: *bool @@ -255,6 +258,9 @@ VirtualMachine: Resource │ │ │ └── "Detach" │ │ ├── Primary: *bool │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsProfile: *Object (9 properties) │ │ ├── AdminPassword: *genruntime.SecretReference │ │ ├── AdminUsername: *string @@ -1176,7 +1182,7 @@ VirtualMachine: Resource └── Zones: string[] VirtualMachineScaleSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (23 properties) +├── Spec: Object (24 properties) │ ├── AdditionalCapabilities: *Object (2 properties) │ │ ├── HibernationEnabled: *bool │ │ └── UltraSSDEnabled: *bool @@ -1204,6 +1210,9 @@ VirtualMachineScaleSet: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestrationMode: *Enum (2 values) │ │ ├── "Flexible" │ │ └── "Uniform" @@ -1890,11 +1899,14 @@ VirtualMachineScaleSet: Resource └── Zones: string[] VirtualMachineScaleSetsExtension: Resource ├── Owner: VirtualMachineScaleSet -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool │ ├── ForceUpdateTag: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtectedSettings: *genruntime.SecretMapReference │ ├── ProtectedSettingsFromKeyVault: *Object (2 properties) @@ -1928,7 +1940,7 @@ VirtualMachineScaleSetsExtension: Resource └── TypeHandlerVersion: *string VirtualMachinesExtension: Resource ├── Owner: VirtualMachine -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoUpgradeMinorVersion: *bool │ ├── AzureName: string │ ├── EnableAutomaticUpgrade: *bool @@ -1956,6 +1968,9 @@ VirtualMachinesExtension: Resource │ │ ├── Type: *string │ │ └── TypeHandlerVersion: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtectedSettings: *genruntime.SecretMapReference │ ├── ProtectedSettingsFromKeyVault: *Object (2 properties) diff --git a/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen.go b/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen.go index 190bd2ceefd..362d9a7497d 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen.go +++ b/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (scaleSet *VirtualMachineScaleSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachineScaleSet resource func (scaleSet *VirtualMachineScaleSet) defaultImpl() { scaleSet.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachineScaleSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (scaleSet *VirtualMachineScaleSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (scaleSet *VirtualMachineScaleSet) SecretDestinationExpressions() []*core.DestinationExpression { + if scaleSet.Spec.OperatorSpec == nil { + return nil + } + return scaleSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualMachineScaleSet{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (scaleSet *VirtualMachineScaleSet) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (scaleSet *VirtualMachineScaleSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){scaleSet.validateResourceReferences, scaleSet.validateOwnerReference} + return []func() (admission.Warnings, error){scaleSet.validateResourceReferences, scaleSet.validateOwnerReference, scaleSet.validateSecretDestinations, scaleSet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (scaleSet *VirtualMachineScaleSet) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return scaleSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return scaleSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return scaleSet.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (scaleSet *VirtualMachineScaleSet) validateConfigMapDestinations() (admission.Warnings, error) { + if scaleSet.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(scaleSet, nil, scaleSet.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (scaleSet *VirtualMachineScaleSet) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (scaleSet *VirtualMachineScaleSet) validateSecretDestinations() (admission.Warnings, error) { + if scaleSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(scaleSet, nil, scaleSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (scaleSet *VirtualMachineScaleSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachineScaleSet) @@ -358,6 +403,10 @@ type VirtualMachineScaleSet_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineScaleSetOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestrationMode: Specifies the orchestration mode for the virtual machine scale set. OrchestrationMode *OrchestrationMode `json:"orchestrationMode,omitempty"` @@ -691,6 +740,8 @@ func (scaleSet *VirtualMachineScaleSet_Spec) PopulateFromARM(owner genruntime.Ar scaleSet.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OrchestrationMode": // copying flattened property: if typedInput.Properties != nil { @@ -980,6 +1031,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_From_VirtualMachin // Location scaleSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + scaleSet.OperatorSpec = &operatorSpec + } else { + scaleSet.OperatorSpec = nil + } + // OrchestrationMode if source.OrchestrationMode != nil { orchestrationMode := *source.OrchestrationMode @@ -1197,6 +1260,18 @@ func (scaleSet *VirtualMachineScaleSet_Spec) AssignProperties_To_VirtualMachineS // Location destination.Location = genruntime.ClonePointerToString(scaleSet.Location) + // OperatorSpec + if scaleSet.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineScaleSetOperatorSpec + err := scaleSet.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestrationMode if scaleSet.OrchestrationMode != nil { orchestrationMode := string(*scaleSet.OrchestrationMode) @@ -4222,6 +4297,110 @@ func (identity *VirtualMachineScaleSetIdentity_STATUS) AssignProperties_To_Virtu return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetOperatorSpec populates our VirtualMachineScaleSetOperatorSpec from the provided source VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_From_VirtualMachineScaleSetOperatorSpec(source *storage.VirtualMachineScaleSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetOperatorSpec populates the provided destination VirtualMachineScaleSetOperatorSpec from our VirtualMachineScaleSetOperatorSpec +func (operator *VirtualMachineScaleSetOperatorSpec) AssignProperties_To_VirtualMachineScaleSetOperatorSpec(destination *storage.VirtualMachineScaleSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Describes a virtual machine scale set virtual machine profile. type VirtualMachineScaleSetVMProfile struct { // ApplicationProfile: Specifies the gallery applications that should be made available to the VM/VMSS diff --git a/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen_test.go b/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen_test.go index b5b07d7d94a..5f0c468f4e5 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen_test.go +++ b/v2/api/compute/v1api20220301/virtual_machine_scale_set_types_gen_test.go @@ -5044,6 +5044,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetOSProfile_STATUS(gens gens["WindowsConfiguration"] = gen.PtrOf(WindowsConfiguration_STATUSGenerator()) } +func Test_VirtualMachineScaleSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetOperatorSpec to VirtualMachineScaleSetOperatorSpec via AssignProperties_To_VirtualMachineScaleSetOperatorSpec & AssignProperties_From_VirtualMachineScaleSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec tests if a specific instance of VirtualMachineScaleSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachineScaleSetOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec, VirtualMachineScaleSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetOperatorSpec(subject VirtualMachineScaleSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetOperatorSpecGenerator() +var virtualMachineScaleSetOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetOperatorSpecGenerator returns a generator of VirtualMachineScaleSetOperatorSpec instances for property testing. +func VirtualMachineScaleSetOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetOperatorSpecGenerator != nil { + return virtualMachineScaleSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetOperatorSpec{}), generators) + + return virtualMachineScaleSetOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetPublicIPAddressConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -6240,6 +6337,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSet_Spec(gens map[string] gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineScaleSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetOperatorSpecGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) gens["ScaleInPolicy"] = gen.PtrOf(ScaleInPolicyGenerator()) diff --git a/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen.go b/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen.go index 9528c277aed..9580b1f471a 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen.go +++ b/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (extension *VirtualMachineScaleSetsExtension) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachineScaleSetsExtension resource func (extension *VirtualMachineScaleSetsExtension) defaultImpl() { extension.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachineScaleSetsExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachineScaleSetsExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachineScaleSetsExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachineScaleSetsExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualMachineScaleSetsExtension{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (extension *VirtualMachineScaleSetsExtension) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (extension *VirtualMachineScaleSetsExtension) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference} + return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference, extension.validateSecretDestinations, extension.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (extension *VirtualMachineScaleSetsExtension) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return extension.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (extension *VirtualMachineScaleSetsExtension) validateConfigMapDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (extension *VirtualMachineScaleSetsExtension) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (extension *VirtualMachineScaleSetsExtension) validateSecretDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (extension *VirtualMachineScaleSetsExtension) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachineScaleSetsExtension) @@ -344,6 +389,10 @@ type VirtualMachineScaleSetsExtension_Spec struct { // update even if the extension configuration has not changed. ForceUpdateTag *string `json:"forceUpdateTag,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineScaleSetsExtensionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -503,6 +552,8 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": extension.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -659,6 +710,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_From_Vi // ForceUpdateTag extension.ForceUpdateTag = genruntime.ClonePointerToString(source.ForceUpdateTag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineScaleSetsExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -751,6 +814,18 @@ func (extension *VirtualMachineScaleSetsExtension_Spec) AssignProperties_To_Virt // ForceUpdateTag destination.ForceUpdateTag = genruntime.ClonePointerToString(extension.ForceUpdateTag) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineScaleSetsExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion() @@ -1577,6 +1652,110 @@ func (reference *KeyVaultSecretReference_STATUS) AssignProperties_To_KeyVaultSec return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineScaleSetsExtensionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec populates our VirtualMachineScaleSetsExtensionOperatorSpec from the provided source VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(source *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec populates the provided destination VirtualMachineScaleSetsExtensionOperatorSpec from our VirtualMachineScaleSetsExtensionOperatorSpec +func (operator *VirtualMachineScaleSetsExtensionOperatorSpec) AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(destination *storage.VirtualMachineScaleSetsExtensionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&VirtualMachineScaleSetsExtension{}, &VirtualMachineScaleSetsExtensionList{}) } diff --git a/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen_test.go b/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen_test.go index f6387af3792..6fd222d4ff9 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen_test.go +++ b/v2/api/compute/v1api20220301/virtual_machine_scale_sets_extension_types_gen_test.go @@ -399,6 +399,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension(gens map[st gens["Status"] = VirtualMachineScaleSetsExtension_STATUSGenerator() } +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineScaleSetsExtensionOperatorSpec to VirtualMachineScaleSetsExtensionOperatorSpec via AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec & AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec tests if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachineScaleSetsExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachineScaleSetsExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineScaleSetsExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineScaleSetsExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec, VirtualMachineScaleSetsExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachineScaleSetsExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineScaleSetsExtensionOperatorSpec(subject VirtualMachineScaleSetsExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineScaleSetsExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator() +var virtualMachineScaleSetsExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachineScaleSetsExtensionOperatorSpecGenerator returns a generator of VirtualMachineScaleSetsExtensionOperatorSpec instances for property testing. +func VirtualMachineScaleSetsExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachineScaleSetsExtensionOperatorSpecGenerator != nil { + return virtualMachineScaleSetsExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineScaleSetsExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineScaleSetsExtensionOperatorSpec{}), generators) + + return virtualMachineScaleSetsExtensionOperatorSpecGenerator +} + func Test_VirtualMachineScaleSetsExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -649,5 +746,6 @@ func AddIndependentPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(ge // AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachineScaleSetsExtension_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineScaleSetsExtensionOperatorSpecGenerator()) gens["ProtectedSettingsFromKeyVault"] = gen.PtrOf(KeyVaultSecretReferenceGenerator()) } diff --git a/v2/api/compute/v1api20220301/virtual_machine_types_gen.go b/v2/api/compute/v1api20220301/virtual_machine_types_gen.go index 05656b0126b..56cb338a021 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_types_gen.go +++ b/v2/api/compute/v1api20220301/virtual_machine_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (machine *VirtualMachine) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachine resource func (machine *VirtualMachine) defaultImpl() { machine.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachine{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (machine *VirtualMachine) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachine{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (machine *VirtualMachine) SecretDestinationExpressions() []*core.DestinationExpression { + if machine.Spec.OperatorSpec == nil { + return nil + } + return machine.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualMachine{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (machine *VirtualMachine) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (machine *VirtualMachine) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){machine.validateResourceReferences, machine.validateOwnerReference} + return []func() (admission.Warnings, error){machine.validateResourceReferences, machine.validateOwnerReference, machine.validateSecretDestinations, machine.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (machine *VirtualMachine) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return machine.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return machine.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return machine.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (machine *VirtualMachine) validateConfigMapDestinations() (admission.Warnings, error) { + if machine.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(machine, nil, machine.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (machine *VirtualMachine) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (machine *VirtualMachine) validateSecretDestinations() (admission.Warnings, error) { + if machine.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(machine, nil, machine.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (machine *VirtualMachine) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachine) @@ -412,6 +457,10 @@ type VirtualMachine_Spec struct { // NetworkProfile: Specifies the network interfaces of the virtual machine. NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachineOperatorSpec `json:"operatorSpec,omitempty"` + // OsProfile: Specifies the operating system settings used while creating the virtual machine. Some of the settings cannot // be changed once VM is provisioned. OsProfile *OSProfile `json:"osProfile,omitempty"` @@ -931,6 +980,8 @@ func (machine *VirtualMachine_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "OsProfile": // copying flattened property: if typedInput.Properties != nil { @@ -1296,6 +1347,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_From_VirtualMachine_Spec(so machine.NetworkProfile = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachineOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachineOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + machine.OperatorSpec = &operatorSpec + } else { + machine.OperatorSpec = nil + } + // OsProfile if source.OsProfile != nil { var osProfile OSProfile @@ -1582,6 +1645,18 @@ func (machine *VirtualMachine_Spec) AssignProperties_To_VirtualMachine_Spec(dest destination.NetworkProfile = nil } + // OperatorSpec + if machine.OperatorSpec != nil { + var operatorSpec storage.VirtualMachineOperatorSpec + err := machine.OperatorSpec.AssignProperties_To_VirtualMachineOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachineOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = machine.OriginalVersion() @@ -8439,6 +8514,110 @@ func (view *VirtualMachineInstanceView_STATUS) AssignProperties_To_VirtualMachin return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachineOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachineOperatorSpec populates our VirtualMachineOperatorSpec from the provided source VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_From_VirtualMachineOperatorSpec(source *storage.VirtualMachineOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachineOperatorSpec populates the provided destination VirtualMachineOperatorSpec from our VirtualMachineOperatorSpec +func (operator *VirtualMachineOperatorSpec) AssignProperties_To_VirtualMachineOperatorSpec(destination *storage.VirtualMachineOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Boot Diagnostics is a debugging feature which allows you to view Console Output and Screenshot to diagnose VM status. // You can easily view the output of your console log. // Azure also enables you to see a screenshot of the diff --git a/v2/api/compute/v1api20220301/virtual_machine_types_gen_test.go b/v2/api/compute/v1api20220301/virtual_machine_types_gen_test.go index ad54422d7c8..d50d9bc8563 100644 --- a/v2/api/compute/v1api20220301/virtual_machine_types_gen_test.go +++ b/v2/api/compute/v1api20220301/virtual_machine_types_gen_test.go @@ -11443,6 +11443,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachineNetworkInterfaceIPConfiguratio gens["Subnet"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_VirtualMachineOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachineOperatorSpec to VirtualMachineOperatorSpec via AssignProperties_To_VirtualMachineOperatorSpec & AssignProperties_From_VirtualMachineOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachineOperatorSpec tests if a specific instance of VirtualMachineOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachineOperatorSpec + err := copied.AssignProperties_To_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachineOperatorSpec + err = actual.AssignProperties_From_VirtualMachineOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachineOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachineOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachineOperatorSpec, VirtualMachineOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachineOperatorSpec runs a test to see if a specific instance of VirtualMachineOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachineOperatorSpec(subject VirtualMachineOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachineOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachineOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachineOperatorSpecGenerator() +var virtualMachineOperatorSpecGenerator gopter.Gen + +// VirtualMachineOperatorSpecGenerator returns a generator of VirtualMachineOperatorSpec instances for property testing. +func VirtualMachineOperatorSpecGenerator() gopter.Gen { + if virtualMachineOperatorSpecGenerator != nil { + return virtualMachineOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachineOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachineOperatorSpec{}), generators) + + return virtualMachineOperatorSpecGenerator +} + func Test_VirtualMachinePatchStatus_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -12292,6 +12389,7 @@ func AddRelatedPropertyGeneratorsForVirtualMachine_Spec(gens map[string]gopter.G gens["HostGroup"] = gen.PtrOf(SubResourceGenerator()) gens["Identity"] = gen.PtrOf(VirtualMachineIdentityGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachineOperatorSpecGenerator()) gens["OsProfile"] = gen.PtrOf(OSProfileGenerator()) gens["Plan"] = gen.PtrOf(PlanGenerator()) gens["ProximityPlacementGroup"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen.go b/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen.go index bc05e29be64..85e44157476 100644 --- a/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen.go +++ b/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (extension *VirtualMachinesExtension) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualMachinesExtension resource func (extension *VirtualMachinesExtension) defaultImpl() { extension.defaultAzureName() } +var _ configmaps.Exporter = &VirtualMachinesExtension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *VirtualMachinesExtension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualMachinesExtension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *VirtualMachinesExtension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualMachinesExtension{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (extension *VirtualMachinesExtension) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (extension *VirtualMachinesExtension) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference} + return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateOwnerReference, extension.validateSecretDestinations, extension.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (extension *VirtualMachinesExtension) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return extension.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (extension *VirtualMachinesExtension) validateConfigMapDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (extension *VirtualMachinesExtension) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (extension *VirtualMachinesExtension) validateSecretDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (extension *VirtualMachinesExtension) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualMachinesExtension) @@ -349,6 +394,10 @@ type VirtualMachinesExtension_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualMachinesExtensionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -547,6 +596,8 @@ func (extension *VirtualMachinesExtension_Spec) PopulateFromARM(owner genruntime extension.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": extension.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -718,6 +769,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_From_VirtualMac // Location extension.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualMachinesExtensionOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + extension.OperatorSpec = &operatorSpec + } else { + extension.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -825,6 +888,18 @@ func (extension *VirtualMachinesExtension_Spec) AssignProperties_To_VirtualMachi // Location destination.Location = genruntime.ClonePointerToString(extension.Location) + // OperatorSpec + if extension.OperatorSpec != nil { + var operatorSpec storage.VirtualMachinesExtensionOperatorSpec + err := extension.OperatorSpec.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualMachinesExtensionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = extension.OriginalVersion() @@ -1949,6 +2024,110 @@ func (view *VirtualMachineExtensionInstanceView_STATUS) AssignProperties_To_Virt return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualMachinesExtensionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualMachinesExtensionOperatorSpec populates our VirtualMachinesExtensionOperatorSpec from the provided source VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_From_VirtualMachinesExtensionOperatorSpec(source *storage.VirtualMachinesExtensionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualMachinesExtensionOperatorSpec populates the provided destination VirtualMachinesExtensionOperatorSpec from our VirtualMachinesExtensionOperatorSpec +func (operator *VirtualMachinesExtensionOperatorSpec) AssignProperties_To_VirtualMachinesExtensionOperatorSpec(destination *storage.VirtualMachinesExtensionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Instance view status. type InstanceViewStatus struct { // Code: The status code. diff --git a/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen_test.go b/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen_test.go index 5c060fcd825..8ea91ca29e8 100644 --- a/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen_test.go +++ b/v2/api/compute/v1api20220301/virtual_machines_extension_types_gen_test.go @@ -511,6 +511,103 @@ func AddRelatedPropertyGeneratorsForVirtualMachinesExtension(gens map[string]gop gens["Status"] = VirtualMachinesExtension_STATUSGenerator() } +func Test_VirtualMachinesExtensionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualMachinesExtensionOperatorSpec to VirtualMachinesExtensionOperatorSpec via AssignProperties_To_VirtualMachinesExtensionOperatorSpec & AssignProperties_From_VirtualMachinesExtensionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec tests if a specific instance of VirtualMachinesExtensionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualMachinesExtensionOperatorSpec + err := copied.AssignProperties_To_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualMachinesExtensionOperatorSpec + err = actual.AssignProperties_From_VirtualMachinesExtensionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualMachinesExtensionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualMachinesExtensionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec, VirtualMachinesExtensionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec runs a test to see if a specific instance of VirtualMachinesExtensionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualMachinesExtensionOperatorSpec(subject VirtualMachinesExtensionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualMachinesExtensionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualMachinesExtensionOperatorSpec instances for property testing - lazily instantiated by +// VirtualMachinesExtensionOperatorSpecGenerator() +var virtualMachinesExtensionOperatorSpecGenerator gopter.Gen + +// VirtualMachinesExtensionOperatorSpecGenerator returns a generator of VirtualMachinesExtensionOperatorSpec instances for property testing. +func VirtualMachinesExtensionOperatorSpecGenerator() gopter.Gen { + if virtualMachinesExtensionOperatorSpecGenerator != nil { + return virtualMachinesExtensionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualMachinesExtensionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualMachinesExtensionOperatorSpec{}), generators) + + return virtualMachinesExtensionOperatorSpecGenerator +} + func Test_VirtualMachinesExtension_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -769,5 +866,6 @@ func AddIndependentPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[s // AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualMachinesExtension_Spec(gens map[string]gopter.Gen) { gens["InstanceView"] = gen.PtrOf(VirtualMachineExtensionInstanceViewGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualMachinesExtensionOperatorSpecGenerator()) gens["ProtectedSettingsFromKeyVault"] = gen.PtrOf(KeyVaultSecretReferenceGenerator()) } diff --git a/v2/api/compute/v1api20220301/zz_generated.deepcopy.go b/v2/api/compute/v1api20220301/zz_generated.deepcopy.go index 1a864bd0c8a..019a6a39e5f 100644 --- a/v2/api/compute/v1api20220301/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20220301/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220301 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -1360,6 +1361,43 @@ func (in *ImageOSDisk_STATUS) DeepCopy() *ImageOSDisk_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImageOperatorSpec) DeepCopyInto(out *ImageOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageOperatorSpec. +func (in *ImageOperatorSpec) DeepCopy() *ImageOperatorSpec { + if in == nil { + return nil + } + out := new(ImageOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageReference) DeepCopyInto(out *ImageReference) { *out = *in @@ -1621,6 +1659,11 @@ func (in *Image_Spec) DeepCopyInto(out *Image_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ImageOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4729,6 +4772,43 @@ func (in *VirtualMachineNetworkInterfaceIPConfiguration_STATUS) DeepCopy() *Virt return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineOperatorSpec) DeepCopyInto(out *VirtualMachineOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineOperatorSpec. +func (in *VirtualMachineOperatorSpec) DeepCopy() *VirtualMachineOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinePatchStatus_STATUS) DeepCopyInto(out *VirtualMachinePatchStatus_STATUS) { *out = *in @@ -6202,6 +6282,43 @@ func (in *VirtualMachineScaleSetOSProfile_STATUS) DeepCopy() *VirtualMachineScal return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetOperatorSpec. +func (in *VirtualMachineScaleSetOperatorSpec) DeepCopy() *VirtualMachineScaleSetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetPublicIPAddressConfiguration) DeepCopyInto(out *VirtualMachineScaleSetPublicIPAddressConfiguration) { *out = *in @@ -6797,6 +6914,11 @@ func (in *VirtualMachineScaleSet_Spec) DeepCopyInto(out *VirtualMachineScaleSet_ *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestrationMode != nil { in, out := &in.OrchestrationMode, &out.OrchestrationMode *out = new(OrchestrationMode) @@ -6945,6 +7067,43 @@ func (in *VirtualMachineScaleSetsExtensionList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopyInto(out *VirtualMachineScaleSetsExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachineScaleSetsExtensionOperatorSpec. +func (in *VirtualMachineScaleSetsExtensionOperatorSpec) DeepCopy() *VirtualMachineScaleSetsExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachineScaleSetsExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachineScaleSetsExtension_STATUS) DeepCopyInto(out *VirtualMachineScaleSetsExtension_STATUS) { *out = *in @@ -7057,6 +7216,11 @@ func (in *VirtualMachineScaleSetsExtension_Spec) DeepCopyInto(out *VirtualMachin *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineScaleSetsExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -7405,6 +7569,11 @@ func (in *VirtualMachine_Spec) DeepCopyInto(out *VirtualMachine_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachineOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsProfile != nil { in, out := &in.OsProfile, &out.OsProfile *out = new(OSProfile) @@ -7543,6 +7712,43 @@ func (in *VirtualMachinesExtensionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopyInto(out *VirtualMachinesExtensionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualMachinesExtensionOperatorSpec. +func (in *VirtualMachinesExtensionOperatorSpec) DeepCopy() *VirtualMachinesExtensionOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualMachinesExtensionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualMachinesExtension_STATUS) DeepCopyInto(out *VirtualMachinesExtension_STATUS) { *out = *in @@ -7677,6 +7883,11 @@ func (in *VirtualMachinesExtension_Spec) DeepCopyInto(out *VirtualMachinesExtens *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualMachinesExtensionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20220702/disk_encryption_set_types_gen.go b/v2/api/compute/v1api20220702/disk_encryption_set_types_gen.go index 58800c18390..8f428e47a31 100644 --- a/v2/api/compute/v1api20220702/disk_encryption_set_types_gen.go +++ b/v2/api/compute/v1api20220702/disk_encryption_set_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +108,26 @@ func (encryptionSet *DiskEncryptionSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the DiskEncryptionSet resource func (encryptionSet *DiskEncryptionSet) defaultImpl() { encryptionSet.defaultAzureName() } +var _ configmaps.Exporter = &DiskEncryptionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryptionSet *DiskEncryptionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskEncryptionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryptionSet *DiskEncryptionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DiskEncryptionSet{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (encryptionSet *DiskEncryptionSet) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (encryptionSet *DiskEncryptionSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){encryptionSet.validateResourceReferences, encryptionSet.validateOwnerReference, encryptionSet.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){encryptionSet.validateResourceReferences, encryptionSet.validateOwnerReference, encryptionSet.validateSecretDestinations, encryptionSet.validateConfigMapDestinations, encryptionSet.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -231,12 +253,26 @@ func (encryptionSet *DiskEncryptionSet) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return encryptionSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return encryptionSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return encryptionSet.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return encryptionSet.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (encryptionSet *DiskEncryptionSet) validateConfigMapDestinations() (admission.Warnings, error) { + if encryptionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(encryptionSet, nil, encryptionSet.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (encryptionSet *DiskEncryptionSet) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&encryptionSet.Spec) @@ -260,6 +296,14 @@ func (encryptionSet *DiskEncryptionSet) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (encryptionSet *DiskEncryptionSet) validateSecretDestinations() (admission.Warnings, error) { + if encryptionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(encryptionSet, nil, encryptionSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (encryptionSet *DiskEncryptionSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DiskEncryptionSet) @@ -373,6 +417,10 @@ type DiskEncryptionSet_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiskEncryptionSetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -532,6 +580,8 @@ func (encryptionSet *DiskEncryptionSet_Spec) PopulateFromARM(owner genruntime.Ar encryptionSet.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": encryptionSet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -662,6 +712,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_From_DiskEncryptio // Location encryptionSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskEncryptionSetOperatorSpec + err := operatorSpec.AssignProperties_From_DiskEncryptionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + encryptionSet.OperatorSpec = &operatorSpec + } else { + encryptionSet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -739,6 +801,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_To_DiskEncryptionS // Location destination.Location = genruntime.ClonePointerToString(encryptionSet.Location) + // OperatorSpec + if encryptionSet.OperatorSpec != nil { + var operatorSpec storage.DiskEncryptionSetOperatorSpec + err := encryptionSet.OperatorSpec.AssignProperties_To_DiskEncryptionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = encryptionSet.OriginalVersion() @@ -1430,6 +1504,110 @@ func (error *ApiError_STATUS) AssignProperties_To_ApiError_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskEncryptionSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskEncryptionSetOperatorSpec populates our DiskEncryptionSetOperatorSpec from the provided source DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_From_DiskEncryptionSetOperatorSpec(source *storage.DiskEncryptionSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiskEncryptionSetOperatorSpec populates the provided destination DiskEncryptionSetOperatorSpec from our DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_To_DiskEncryptionSetOperatorSpec(destination *storage.DiskEncryptionSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The type of key used to encrypt the data of the disk. // +kubebuilder:validation:Enum={"ConfidentialVmEncryptedWithCustomerKey","EncryptionAtRestWithCustomerKey","EncryptionAtRestWithPlatformAndCustomerKeys"} type DiskEncryptionSetType string diff --git a/v2/api/compute/v1api20220702/disk_encryption_set_types_gen_test.go b/v2/api/compute/v1api20220702/disk_encryption_set_types_gen_test.go index 6ec58bcd6fc..a4c265180ce 100644 --- a/v2/api/compute/v1api20220702/disk_encryption_set_types_gen_test.go +++ b/v2/api/compute/v1api20220702/disk_encryption_set_types_gen_test.go @@ -389,6 +389,103 @@ func AddRelatedPropertyGeneratorsForDiskEncryptionSet(gens map[string]gopter.Gen gens["Status"] = DiskEncryptionSet_STATUSGenerator() } +func Test_DiskEncryptionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskEncryptionSetOperatorSpec to DiskEncryptionSetOperatorSpec via AssignProperties_To_DiskEncryptionSetOperatorSpec & AssignProperties_From_DiskEncryptionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec tests if a specific instance of DiskEncryptionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220702s.DiskEncryptionSetOperatorSpec + err := copied.AssignProperties_To_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskEncryptionSetOperatorSpec + err = actual.AssignProperties_From_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskEncryptionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskEncryptionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskEncryptionSetOperatorSpec runs a test to see if a specific instance of DiskEncryptionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskEncryptionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskEncryptionSetOperatorSpec instances for property testing - lazily instantiated by +// DiskEncryptionSetOperatorSpecGenerator() +var diskEncryptionSetOperatorSpecGenerator gopter.Gen + +// DiskEncryptionSetOperatorSpecGenerator returns a generator of DiskEncryptionSetOperatorSpec instances for property testing. +func DiskEncryptionSetOperatorSpecGenerator() gopter.Gen { + if diskEncryptionSetOperatorSpecGenerator != nil { + return diskEncryptionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskEncryptionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskEncryptionSetOperatorSpec{}), generators) + + return diskEncryptionSetOperatorSpecGenerator +} + func Test_DiskEncryptionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -643,6 +740,7 @@ func AddIndependentPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]gopter.Gen) { gens["ActiveKey"] = gen.PtrOf(KeyForDiskEncryptionSetGenerator()) gens["Identity"] = gen.PtrOf(EncryptionSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskEncryptionSetOperatorSpecGenerator()) } func Test_EncryptionSetIdentity_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen.go b/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen.go index 9b6b35abd26..f2ccf72b78c 100644 --- a/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen.go +++ b/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/compute/v1api20240302/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (encryptionSet *DiskEncryptionSet) ConvertTo(hub conversion.Hub) error { return encryptionSet.AssignProperties_To_DiskEncryptionSet(destination) } +var _ configmaps.Exporter = &DiskEncryptionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryptionSet *DiskEncryptionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskEncryptionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryptionSet *DiskEncryptionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DiskEncryptionSet{} // AzureName returns the Azure name of the resource @@ -249,6 +272,7 @@ type DiskEncryptionSet_Spec struct { FederatedClientIdFromConfig *genruntime.ConfigMapReference `json:"federatedClientIdFromConfig,omitempty" optionalConfigMapPair:"FederatedClientId"` Identity *EncryptionSetIdentity `json:"identity,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *DiskEncryptionSetOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -360,6 +384,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_From_DiskEncryptio // Location encryptionSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskEncryptionSetOperatorSpec + err := operatorSpec.AssignProperties_From_DiskEncryptionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + encryptionSet.OperatorSpec = &operatorSpec + } else { + encryptionSet.OperatorSpec = nil + } + // OriginalVersion encryptionSet.OriginalVersion = source.OriginalVersion @@ -451,6 +487,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_To_DiskEncryptionS // Location destination.Location = genruntime.ClonePointerToString(encryptionSet.Location) + // OperatorSpec + if encryptionSet.OperatorSpec != nil { + var operatorSpec storage.DiskEncryptionSetOperatorSpec + err := encryptionSet.OperatorSpec.AssignProperties_To_DiskEncryptionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = encryptionSet.OriginalVersion @@ -947,6 +995,136 @@ type augmentConversionForDiskEncryptionSet_STATUS interface { AssignPropertiesTo(dst *storage.DiskEncryptionSet_STATUS) error } +// Storage version of v1api20220702.DiskEncryptionSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskEncryptionSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskEncryptionSetOperatorSpec populates our DiskEncryptionSetOperatorSpec from the provided source DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_From_DiskEncryptionSetOperatorSpec(source *storage.DiskEncryptionSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForDiskEncryptionSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForDiskEncryptionSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_DiskEncryptionSetOperatorSpec populates the provided destination DiskEncryptionSetOperatorSpec from our DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_To_DiskEncryptionSetOperatorSpec(destination *storage.DiskEncryptionSetOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForDiskEncryptionSetOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForDiskEncryptionSetOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20220702.EncryptionSetIdentity // The managed identity for the disk encryption set. It should be given permission on the key vault before it can be used // to encrypt disks. @@ -1438,6 +1616,11 @@ type augmentConversionForApiError_STATUS interface { AssignPropertiesTo(dst *storage.ApiError_STATUS) error } +type augmentConversionForDiskEncryptionSetOperatorSpec interface { + AssignPropertiesFrom(src *storage.DiskEncryptionSetOperatorSpec) error + AssignPropertiesTo(dst *storage.DiskEncryptionSetOperatorSpec) error +} + type augmentConversionForEncryptionSetIdentity interface { AssignPropertiesFrom(src *storage.EncryptionSetIdentity) error AssignPropertiesTo(dst *storage.EncryptionSetIdentity) error diff --git a/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen_test.go b/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen_test.go index a61d82cd9ff..282269278d3 100644 --- a/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen_test.go +++ b/v2/api/compute/v1api20220702/storage/disk_encryption_set_types_gen_test.go @@ -388,6 +388,103 @@ func AddRelatedPropertyGeneratorsForDiskEncryptionSet(gens map[string]gopter.Gen gens["Status"] = DiskEncryptionSet_STATUSGenerator() } +func Test_DiskEncryptionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskEncryptionSetOperatorSpec to DiskEncryptionSetOperatorSpec via AssignProperties_To_DiskEncryptionSetOperatorSpec & AssignProperties_From_DiskEncryptionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec tests if a specific instance of DiskEncryptionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DiskEncryptionSetOperatorSpec + err := copied.AssignProperties_To_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskEncryptionSetOperatorSpec + err = actual.AssignProperties_From_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskEncryptionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskEncryptionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskEncryptionSetOperatorSpec runs a test to see if a specific instance of DiskEncryptionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskEncryptionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskEncryptionSetOperatorSpec instances for property testing - lazily instantiated by +// DiskEncryptionSetOperatorSpecGenerator() +var diskEncryptionSetOperatorSpecGenerator gopter.Gen + +// DiskEncryptionSetOperatorSpecGenerator returns a generator of DiskEncryptionSetOperatorSpec instances for property testing. +func DiskEncryptionSetOperatorSpecGenerator() gopter.Gen { + if diskEncryptionSetOperatorSpecGenerator != nil { + return diskEncryptionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskEncryptionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskEncryptionSetOperatorSpec{}), generators) + + return diskEncryptionSetOperatorSpecGenerator +} + func Test_DiskEncryptionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -643,6 +740,7 @@ func AddIndependentPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]gopter.Gen) { gens["ActiveKey"] = gen.PtrOf(KeyForDiskEncryptionSetGenerator()) gens["Identity"] = gen.PtrOf(EncryptionSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskEncryptionSetOperatorSpecGenerator()) } func Test_EncryptionSetIdentity_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/compute/v1api20220702/storage/structure.txt b/v2/api/compute/v1api20220702/storage/structure.txt index 9ca06de3ca5..1cec8b59382 100644 --- a/v2/api/compute/v1api20220702/storage/structure.txt +++ b/v2/api/compute/v1api20220702/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-07-02" DiskEncryptionSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── ActiveKey: *Object (4 properties) │ │ ├── KeyUrl: *string │ │ ├── KeyUrlFromConfig: *genruntime.ConfigMapReference @@ -24,6 +24,10 @@ DiskEncryptionSet: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -80,6 +84,7 @@ DiskEncryptionSet: Resource augmentConversionForApiErrorBase_STATUS: Interface augmentConversionForApiError_STATUS: Interface augmentConversionForDiskEncryptionSet: Interface +augmentConversionForDiskEncryptionSetOperatorSpec: Interface augmentConversionForDiskEncryptionSet_STATUS: Interface augmentConversionForDiskEncryptionSet_Spec: Interface augmentConversionForEncryptionSetIdentity: Interface diff --git a/v2/api/compute/v1api20220702/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20220702/storage/zz_generated.deepcopy.go index 8e1d954a819..915e766bb2d 100644 --- a/v2/api/compute/v1api20220702/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20220702/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -160,6 +161,50 @@ func (in *DiskEncryptionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskEncryptionSetOperatorSpec) DeepCopyInto(out *DiskEncryptionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSetOperatorSpec. +func (in *DiskEncryptionSetOperatorSpec) DeepCopy() *DiskEncryptionSetOperatorSpec { + if in == nil { + return nil + } + out := new(DiskEncryptionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSet_STATUS) DeepCopyInto(out *DiskEncryptionSet_STATUS) { *out = *in @@ -296,6 +341,11 @@ func (in *DiskEncryptionSet_Spec) DeepCopyInto(out *DiskEncryptionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskEncryptionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20220702/structure.txt b/v2/api/compute/v1api20220702/structure.txt index db2ab53b831..858a9ea55cb 100644 --- a/v2/api/compute/v1api20220702/structure.txt +++ b/v2/api/compute/v1api20220702/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-07-02" DiskEncryptionSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── ActiveKey: *Object (3 properties) │ │ ├── KeyUrl: *string │ │ ├── KeyUrlFromConfig: *genruntime.ConfigMapReference @@ -27,6 +27,9 @@ DiskEncryptionSet: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RotationToLatestKeyVersionEnabled: *bool │ └── Tags: map[string]string diff --git a/v2/api/compute/v1api20220702/zz_generated.deepcopy.go b/v2/api/compute/v1api20220702/zz_generated.deepcopy.go index d32d1b26590..4db1be50387 100644 --- a/v2/api/compute/v1api20220702/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20220702/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220702 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -146,6 +147,43 @@ func (in *DiskEncryptionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskEncryptionSetOperatorSpec) DeepCopyInto(out *DiskEncryptionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSetOperatorSpec. +func (in *DiskEncryptionSetOperatorSpec) DeepCopy() *DiskEncryptionSetOperatorSpec { + if in == nil { + return nil + } + out := new(DiskEncryptionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSet_STATUS) DeepCopyInto(out *DiskEncryptionSet_STATUS) { *out = *in @@ -275,6 +313,11 @@ func (in *DiskEncryptionSet_Spec) DeepCopyInto(out *DiskEncryptionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskEncryptionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/compute/v1api20240302/disk_access_types_gen.go b/v2/api/compute/v1api20240302/disk_access_types_gen.go index d9d1eabaf62..46d9933ab7d 100644 --- a/v2/api/compute/v1api20240302/disk_access_types_gen.go +++ b/v2/api/compute/v1api20240302/disk_access_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (access *DiskAccess) defaultAzureName() { // defaultImpl applies the code generated defaults to the DiskAccess resource func (access *DiskAccess) defaultImpl() { access.defaultAzureName() } +var _ configmaps.Exporter = &DiskAccess{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (access *DiskAccess) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if access.Spec.OperatorSpec == nil { + return nil + } + return access.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskAccess{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (access *DiskAccess) SecretDestinationExpressions() []*core.DestinationExpression { + if access.Spec.OperatorSpec == nil { + return nil + } + return access.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DiskAccess{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (access *DiskAccess) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (access *DiskAccess) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){access.validateResourceReferences, access.validateOwnerReference} + return []func() (admission.Warnings, error){access.validateResourceReferences, access.validateOwnerReference, access.validateSecretDestinations, access.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (access *DiskAccess) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return access.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return access.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return access.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (access *DiskAccess) validateConfigMapDestinations() (admission.Warnings, error) { + if access.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(access, nil, access.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (access *DiskAccess) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (access *DiskAccess) validateSecretDestinations() (admission.Warnings, error) { + if access.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(access, nil, access.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (access *DiskAccess) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DiskAccess) @@ -337,6 +382,10 @@ type DiskAccess_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiskAccessOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -417,6 +466,8 @@ func (access *DiskAccess_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe access.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": access.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -506,6 +557,18 @@ func (access *DiskAccess_Spec) AssignProperties_From_DiskAccess_Spec(source *sto // Location access.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskAccessOperatorSpec + err := operatorSpec.AssignProperties_From_DiskAccessOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskAccessOperatorSpec() to populate field OperatorSpec") + } + access.OperatorSpec = &operatorSpec + } else { + access.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -544,6 +607,18 @@ func (access *DiskAccess_Spec) AssignProperties_To_DiskAccess_Spec(destination * // Location destination.Location = genruntime.ClonePointerToString(access.Location) + // OperatorSpec + if access.OperatorSpec != nil { + var operatorSpec storage.DiskAccessOperatorSpec + err := access.OperatorSpec.AssignProperties_To_DiskAccessOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskAccessOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = access.OriginalVersion() @@ -911,6 +986,110 @@ func (access *DiskAccess_STATUS) AssignProperties_To_DiskAccess_STATUS(destinati return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskAccessOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskAccessOperatorSpec populates our DiskAccessOperatorSpec from the provided source DiskAccessOperatorSpec +func (operator *DiskAccessOperatorSpec) AssignProperties_From_DiskAccessOperatorSpec(source *storage.DiskAccessOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiskAccessOperatorSpec populates the provided destination DiskAccessOperatorSpec from our DiskAccessOperatorSpec +func (operator *DiskAccessOperatorSpec) AssignProperties_To_DiskAccessOperatorSpec(destination *storage.DiskAccessOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The Private Endpoint Connection resource. type PrivateEndpointConnection_STATUS struct { // Id: private endpoint connection Id diff --git a/v2/api/compute/v1api20240302/disk_access_types_gen_test.go b/v2/api/compute/v1api20240302/disk_access_types_gen_test.go index b587f782443..858326d15b0 100644 --- a/v2/api/compute/v1api20240302/disk_access_types_gen_test.go +++ b/v2/api/compute/v1api20240302/disk_access_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDiskAccess(gens map[string]gopter.Gen) { gens["Status"] = DiskAccess_STATUSGenerator() } +func Test_DiskAccessOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskAccessOperatorSpec to DiskAccessOperatorSpec via AssignProperties_To_DiskAccessOperatorSpec & AssignProperties_From_DiskAccessOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskAccessOperatorSpec, DiskAccessOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskAccessOperatorSpec tests if a specific instance of DiskAccessOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskAccessOperatorSpec(subject DiskAccessOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DiskAccessOperatorSpec + err := copied.AssignProperties_To_DiskAccessOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskAccessOperatorSpec + err = actual.AssignProperties_From_DiskAccessOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskAccessOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskAccessOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskAccessOperatorSpec, DiskAccessOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskAccessOperatorSpec runs a test to see if a specific instance of DiskAccessOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskAccessOperatorSpec(subject DiskAccessOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskAccessOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskAccessOperatorSpec instances for property testing - lazily instantiated by +// DiskAccessOperatorSpecGenerator() +var diskAccessOperatorSpecGenerator gopter.Gen + +// DiskAccessOperatorSpecGenerator returns a generator of DiskAccessOperatorSpec instances for property testing. +func DiskAccessOperatorSpecGenerator() gopter.Gen { + if diskAccessOperatorSpecGenerator != nil { + return diskAccessOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskAccessOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskAccessOperatorSpec{}), generators) + + return diskAccessOperatorSpecGenerator +} + func Test_DiskAccess_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForDiskAccess_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForDiskAccess_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDiskAccess_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskAccessOperatorSpecGenerator()) } func Test_PrivateEndpointConnection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/compute/v1api20240302/disk_encryption_set_types_gen.go b/v2/api/compute/v1api20240302/disk_encryption_set_types_gen.go index eb11cfccb60..7daa1a7bb81 100644 --- a/v2/api/compute/v1api20240302/disk_encryption_set_types_gen.go +++ b/v2/api/compute/v1api20240302/disk_encryption_set_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (encryptionSet *DiskEncryptionSet) defaultAzureName() { // defaultImpl applies the code generated defaults to the DiskEncryptionSet resource func (encryptionSet *DiskEncryptionSet) defaultImpl() { encryptionSet.defaultAzureName() } +var _ configmaps.Exporter = &DiskEncryptionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryptionSet *DiskEncryptionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskEncryptionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryptionSet *DiskEncryptionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DiskEncryptionSet{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (encryptionSet *DiskEncryptionSet) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (encryptionSet *DiskEncryptionSet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){encryptionSet.validateResourceReferences, encryptionSet.validateOwnerReference, encryptionSet.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){encryptionSet.validateResourceReferences, encryptionSet.validateOwnerReference, encryptionSet.validateSecretDestinations, encryptionSet.validateConfigMapDestinations, encryptionSet.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (encryptionSet *DiskEncryptionSet) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return encryptionSet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return encryptionSet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return encryptionSet.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return encryptionSet.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (encryptionSet *DiskEncryptionSet) validateConfigMapDestinations() (admission.Warnings, error) { + if encryptionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(encryptionSet, nil, encryptionSet.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (encryptionSet *DiskEncryptionSet) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&encryptionSet.Spec) @@ -257,6 +293,14 @@ func (encryptionSet *DiskEncryptionSet) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (encryptionSet *DiskEncryptionSet) validateSecretDestinations() (admission.Warnings, error) { + if encryptionSet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(encryptionSet, nil, encryptionSet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (encryptionSet *DiskEncryptionSet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DiskEncryptionSet) @@ -365,6 +409,10 @@ type DiskEncryptionSet_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiskEncryptionSetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -524,6 +572,8 @@ func (encryptionSet *DiskEncryptionSet_Spec) PopulateFromARM(owner genruntime.Ar encryptionSet.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": encryptionSet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -654,6 +704,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_From_DiskEncryptio // Location encryptionSet.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskEncryptionSetOperatorSpec + err := operatorSpec.AssignProperties_From_DiskEncryptionSetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + encryptionSet.OperatorSpec = &operatorSpec + } else { + encryptionSet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -731,6 +793,18 @@ func (encryptionSet *DiskEncryptionSet_Spec) AssignProperties_To_DiskEncryptionS // Location destination.Location = genruntime.ClonePointerToString(encryptionSet.Location) + // OperatorSpec + if encryptionSet.OperatorSpec != nil { + var operatorSpec storage.DiskEncryptionSetOperatorSpec + err := encryptionSet.OperatorSpec.AssignProperties_To_DiskEncryptionSetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskEncryptionSetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = encryptionSet.OriginalVersion() @@ -1478,6 +1552,110 @@ func (error *ApiError_STATUS) AssignProperties_To_ApiError_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskEncryptionSetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskEncryptionSetOperatorSpec populates our DiskEncryptionSetOperatorSpec from the provided source DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_From_DiskEncryptionSetOperatorSpec(source *storage.DiskEncryptionSetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiskEncryptionSetOperatorSpec populates the provided destination DiskEncryptionSetOperatorSpec from our DiskEncryptionSetOperatorSpec +func (operator *DiskEncryptionSetOperatorSpec) AssignProperties_To_DiskEncryptionSetOperatorSpec(destination *storage.DiskEncryptionSetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The type of key used to encrypt the data of the disk. // +kubebuilder:validation:Enum={"ConfidentialVmEncryptedWithCustomerKey","EncryptionAtRestWithCustomerKey","EncryptionAtRestWithPlatformAndCustomerKeys"} type DiskEncryptionSetType string diff --git a/v2/api/compute/v1api20240302/disk_encryption_set_types_gen_test.go b/v2/api/compute/v1api20240302/disk_encryption_set_types_gen_test.go index f7e3d192260..6f2129f3597 100644 --- a/v2/api/compute/v1api20240302/disk_encryption_set_types_gen_test.go +++ b/v2/api/compute/v1api20240302/disk_encryption_set_types_gen_test.go @@ -388,6 +388,103 @@ func AddRelatedPropertyGeneratorsForDiskEncryptionSet(gens map[string]gopter.Gen gens["Status"] = DiskEncryptionSet_STATUSGenerator() } +func Test_DiskEncryptionSetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskEncryptionSetOperatorSpec to DiskEncryptionSetOperatorSpec via AssignProperties_To_DiskEncryptionSetOperatorSpec & AssignProperties_From_DiskEncryptionSetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec tests if a specific instance of DiskEncryptionSetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DiskEncryptionSetOperatorSpec + err := copied.AssignProperties_To_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskEncryptionSetOperatorSpec + err = actual.AssignProperties_From_DiskEncryptionSetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskEncryptionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskEncryptionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskEncryptionSetOperatorSpec runs a test to see if a specific instance of DiskEncryptionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskEncryptionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskEncryptionSetOperatorSpec instances for property testing - lazily instantiated by +// DiskEncryptionSetOperatorSpecGenerator() +var diskEncryptionSetOperatorSpecGenerator gopter.Gen + +// DiskEncryptionSetOperatorSpecGenerator returns a generator of DiskEncryptionSetOperatorSpec instances for property testing. +func DiskEncryptionSetOperatorSpecGenerator() gopter.Gen { + if diskEncryptionSetOperatorSpecGenerator != nil { + return diskEncryptionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskEncryptionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskEncryptionSetOperatorSpec{}), generators) + + return diskEncryptionSetOperatorSpecGenerator +} + func Test_DiskEncryptionSet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -642,6 +739,7 @@ func AddIndependentPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]gopter.Gen) { gens["ActiveKey"] = gen.PtrOf(KeyForDiskEncryptionSetGenerator()) gens["Identity"] = gen.PtrOf(EncryptionSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskEncryptionSetOperatorSpecGenerator()) } func Test_EncryptionSetIdentity_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/compute/v1api20240302/disk_types_gen.go b/v2/api/compute/v1api20240302/disk_types_gen.go index a424e9806b9..676d43e640a 100644 --- a/v2/api/compute/v1api20240302/disk_types_gen.go +++ b/v2/api/compute/v1api20240302/disk_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (disk *Disk) defaultAzureName() { // defaultImpl applies the code generated defaults to the Disk resource func (disk *Disk) defaultImpl() { disk.defaultAzureName() } +var _ configmaps.Exporter = &Disk{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (disk *Disk) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Disk{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (disk *Disk) SecretDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Disk{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (disk *Disk) ValidateUpdate(old runtime.Object) (admission.Warnings, error) // createValidations validates the creation of the resource func (disk *Disk) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){disk.validateResourceReferences, disk.validateOwnerReference} + return []func() (admission.Warnings, error){disk.validateResourceReferences, disk.validateOwnerReference, disk.validateSecretDestinations, disk.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (disk *Disk) updateValidations() []func(old runtime.Object) (admission.Warn func(old runtime.Object) (admission.Warnings, error) { return disk.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return disk.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return disk.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (disk *Disk) validateConfigMapDestinations() (admission.Warnings, error) { + if disk.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(disk, nil, disk.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (disk *Disk) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (disk *Disk) validateSecretDestinations() (admission.Warnings, error) { + if disk.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(disk, nil, disk.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (disk *Disk) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Disk) @@ -397,6 +442,10 @@ type Disk_Spec struct { // NetworkAccessPolicy: Policy for accessing the disk via network. NetworkAccessPolicy *NetworkAccessPolicy `json:"networkAccessPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiskOperatorSpec `json:"operatorSpec,omitempty"` + // OptimizedForFrequentAttach: Setting this property to true improves reliability and performance of data disks that are // frequently (more than 5 times a day) by detached from one virtual machine and attached to another. This property should // not be set for disks that are not detached and attached frequently as it causes the disks to not align with the fault @@ -834,6 +883,8 @@ func (disk *Disk_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, } } + // no assignment for property "OperatorSpec" + // Set property "OptimizedForFrequentAttach": // copying flattened property: if typedInput.Properties != nil { @@ -1135,6 +1186,18 @@ func (disk *Disk_Spec) AssignProperties_From_Disk_Spec(source *storage.Disk_Spec disk.NetworkAccessPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiskOperatorSpec + err := operatorSpec.AssignProperties_From_DiskOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiskOperatorSpec() to populate field OperatorSpec") + } + disk.OperatorSpec = &operatorSpec + } else { + disk.OperatorSpec = nil + } + // OptimizedForFrequentAttach if source.OptimizedForFrequentAttach != nil { optimizedForFrequentAttach := *source.OptimizedForFrequentAttach @@ -1363,6 +1426,18 @@ func (disk *Disk_Spec) AssignProperties_To_Disk_Spec(destination *storage.Disk_S destination.NetworkAccessPolicy = nil } + // OperatorSpec + if disk.OperatorSpec != nil { + var operatorSpec storage.DiskOperatorSpec + err := disk.OperatorSpec.AssignProperties_To_DiskOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiskOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptimizedForFrequentAttach if disk.OptimizedForFrequentAttach != nil { optimizedForFrequentAttach := *disk.OptimizedForFrequentAttach @@ -3773,6 +3848,110 @@ var dataAccessAuthMode_STATUS_Values = map[string]DataAccessAuthMode_STATUS{ "none": DataAccessAuthMode_STATUS_None, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiskOperatorSpec populates our DiskOperatorSpec from the provided source DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_From_DiskOperatorSpec(source *storage.DiskOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiskOperatorSpec populates the provided destination DiskOperatorSpec from our DiskOperatorSpec +func (operator *DiskOperatorSpec) AssignProperties_To_DiskOperatorSpec(destination *storage.DiskOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"V1","V2"} type DiskProperties_HyperVGeneration string diff --git a/v2/api/compute/v1api20240302/disk_types_gen_test.go b/v2/api/compute/v1api20240302/disk_types_gen_test.go index 96ab3f04b84..ed61db6b389 100644 --- a/v2/api/compute/v1api20240302/disk_types_gen_test.go +++ b/v2/api/compute/v1api20240302/disk_types_gen_test.go @@ -438,6 +438,102 @@ func AddRelatedPropertyGeneratorsForDisk(gens map[string]gopter.Gen) { gens["Status"] = Disk_STATUSGenerator() } +func Test_DiskOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiskOperatorSpec to DiskOperatorSpec via AssignProperties_To_DiskOperatorSpec & AssignProperties_From_DiskOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiskOperatorSpec tests if a specific instance of DiskOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DiskOperatorSpec + err := copied.AssignProperties_To_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiskOperatorSpec + err = actual.AssignProperties_From_DiskOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiskOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskOperatorSpec runs a test to see if a specific instance of DiskOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskOperatorSpec instances for property testing - lazily instantiated by DiskOperatorSpecGenerator() +var diskOperatorSpecGenerator gopter.Gen + +// DiskOperatorSpecGenerator returns a generator of DiskOperatorSpec instances for property testing. +func DiskOperatorSpecGenerator() gopter.Gen { + if diskOperatorSpecGenerator != nil { + return diskOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskOperatorSpec{}), generators) + + return diskOperatorSpecGenerator +} + func Test_DiskSecurityProfile_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1178,6 +1274,7 @@ func AddRelatedPropertyGeneratorsForDisk_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["SecurityProfile"] = gen.PtrOf(DiskSecurityProfileGenerator()) gens["Sku"] = gen.PtrOf(DiskSkuGenerator()) diff --git a/v2/api/compute/v1api20240302/snapshot_types_gen.go b/v2/api/compute/v1api20240302/snapshot_types_gen.go index bd88d356dbc..08d234cdccb 100644 --- a/v2/api/compute/v1api20240302/snapshot_types_gen.go +++ b/v2/api/compute/v1api20240302/snapshot_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (snapshot *Snapshot) defaultAzureName() { // defaultImpl applies the code generated defaults to the Snapshot resource func (snapshot *Snapshot) defaultImpl() { snapshot.defaultAzureName() } +var _ configmaps.Exporter = &Snapshot{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (snapshot *Snapshot) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Snapshot{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (snapshot *Snapshot) SecretDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Snapshot{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (snapshot *Snapshot) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (snapshot *Snapshot) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){snapshot.validateResourceReferences, snapshot.validateOwnerReference} + return []func() (admission.Warnings, error){snapshot.validateResourceReferences, snapshot.validateOwnerReference, snapshot.validateSecretDestinations, snapshot.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (snapshot *Snapshot) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return snapshot.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return snapshot.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return snapshot.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (snapshot *Snapshot) validateConfigMapDestinations() (admission.Warnings, error) { + if snapshot.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(snapshot, nil, snapshot.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (snapshot *Snapshot) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(snapshot) @@ -244,6 +281,14 @@ func (snapshot *Snapshot) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (snapshot *Snapshot) validateSecretDestinations() (admission.Warnings, error) { + if snapshot.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(snapshot, nil, snapshot.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (snapshot *Snapshot) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Snapshot) @@ -379,6 +424,10 @@ type Snapshot_Spec struct { // NetworkAccessPolicy: Policy for accessing the disk via network. NetworkAccessPolicy *NetworkAccessPolicy `json:"networkAccessPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SnapshotOperatorSpec `json:"operatorSpec,omitempty"` + // OsType: The Operating System type. OsType *SnapshotProperties_OsType `json:"osType,omitempty"` @@ -759,6 +808,8 @@ func (snapshot *Snapshot_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe } } + // no assignment for property "OperatorSpec" + // Set property "OsType": // copying flattened property: if typedInput.Properties != nil { @@ -1043,6 +1094,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_From_Snapshot_Spec(source *stora snapshot.NetworkAccessPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SnapshotOperatorSpec + err := operatorSpec.AssignProperties_From_SnapshotOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SnapshotOperatorSpec() to populate field OperatorSpec") + } + snapshot.OperatorSpec = &operatorSpec + } else { + snapshot.OperatorSpec = nil + } + // OsType if source.OsType != nil { osType := *source.OsType @@ -1262,6 +1325,18 @@ func (snapshot *Snapshot_Spec) AssignProperties_To_Snapshot_Spec(destination *st destination.NetworkAccessPolicy = nil } + // OperatorSpec + if snapshot.OperatorSpec != nil { + var operatorSpec storage.SnapshotOperatorSpec + err := snapshot.OperatorSpec.AssignProperties_To_SnapshotOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SnapshotOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = snapshot.OriginalVersion() @@ -2779,6 +2854,110 @@ var diskState_Values = map[string]DiskState{ "unattached": DiskState_Unattached, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SnapshotOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SnapshotOperatorSpec populates our SnapshotOperatorSpec from the provided source SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_From_SnapshotOperatorSpec(source *storage.SnapshotOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SnapshotOperatorSpec populates the provided destination SnapshotOperatorSpec from our SnapshotOperatorSpec +func (operator *SnapshotOperatorSpec) AssignProperties_To_SnapshotOperatorSpec(destination *storage.SnapshotOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"V1","V2"} type SnapshotProperties_HyperVGeneration string diff --git a/v2/api/compute/v1api20240302/snapshot_types_gen_test.go b/v2/api/compute/v1api20240302/snapshot_types_gen_test.go index e8456397c13..c9503ac0670 100644 --- a/v2/api/compute/v1api20240302/snapshot_types_gen_test.go +++ b/v2/api/compute/v1api20240302/snapshot_types_gen_test.go @@ -372,6 +372,103 @@ func AddRelatedPropertyGeneratorsForSnapshot(gens map[string]gopter.Gen) { gens["Status"] = Snapshot_STATUSGenerator() } +func Test_SnapshotOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SnapshotOperatorSpec to SnapshotOperatorSpec via AssignProperties_To_SnapshotOperatorSpec & AssignProperties_From_SnapshotOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSnapshotOperatorSpec tests if a specific instance of SnapshotOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SnapshotOperatorSpec + err := copied.AssignProperties_To_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SnapshotOperatorSpec + err = actual.AssignProperties_From_SnapshotOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SnapshotOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SnapshotOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSnapshotOperatorSpec runs a test to see if a specific instance of SnapshotOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SnapshotOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SnapshotOperatorSpec instances for property testing - lazily instantiated by +// SnapshotOperatorSpecGenerator() +var snapshotOperatorSpecGenerator gopter.Gen + +// SnapshotOperatorSpecGenerator returns a generator of SnapshotOperatorSpec instances for property testing. +func SnapshotOperatorSpecGenerator() gopter.Gen { + if snapshotOperatorSpecGenerator != nil { + return snapshotOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + snapshotOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SnapshotOperatorSpec{}), generators) + + return snapshotOperatorSpecGenerator +} + func Test_SnapshotSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -872,6 +969,7 @@ func AddRelatedPropertyGeneratorsForSnapshot_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SnapshotOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["SecurityProfile"] = gen.PtrOf(DiskSecurityProfileGenerator()) gens["Sku"] = gen.PtrOf(SnapshotSkuGenerator()) diff --git a/v2/api/compute/v1api20240302/storage/disk_access_types_gen.go b/v2/api/compute/v1api20240302/storage/disk_access_types_gen.go index ebc973f4814..47efc979a18 100644 --- a/v2/api/compute/v1api20240302/storage/disk_access_types_gen.go +++ b/v2/api/compute/v1api20240302/storage/disk_access_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (access *DiskAccess) SetConditions(conditions conditions.Conditions) { access.Status.Conditions = conditions } +var _ configmaps.Exporter = &DiskAccess{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (access *DiskAccess) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if access.Spec.OperatorSpec == nil { + return nil + } + return access.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskAccess{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (access *DiskAccess) SecretDestinationExpressions() []*core.DestinationExpression { + if access.Spec.OperatorSpec == nil { + return nil + } + return access.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DiskAccess{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type DiskAccessList struct { type DiskAccess_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DiskAccessOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -212,6 +236,14 @@ func (access *DiskAccess_STATUS) ConvertStatusTo(destination genruntime.Converti return destination.ConvertStatusFrom(access) } +// Storage version of v1api20240302.DiskAccessOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskAccessOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240302.PrivateEndpointConnection_STATUS // The Private Endpoint Connection resource. type PrivateEndpointConnection_STATUS struct { diff --git a/v2/api/compute/v1api20240302/storage/disk_access_types_gen_test.go b/v2/api/compute/v1api20240302/storage/disk_access_types_gen_test.go index 8e36a641b6a..cde0663f75c 100644 --- a/v2/api/compute/v1api20240302/storage/disk_access_types_gen_test.go +++ b/v2/api/compute/v1api20240302/storage/disk_access_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDiskAccess(gens map[string]gopter.Gen) { gens["Status"] = DiskAccess_STATUSGenerator() } +func Test_DiskAccessOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskAccessOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskAccessOperatorSpec, DiskAccessOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskAccessOperatorSpec runs a test to see if a specific instance of DiskAccessOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskAccessOperatorSpec(subject DiskAccessOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskAccessOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskAccessOperatorSpec instances for property testing - lazily instantiated by +// DiskAccessOperatorSpecGenerator() +var diskAccessOperatorSpecGenerator gopter.Gen + +// DiskAccessOperatorSpecGenerator returns a generator of DiskAccessOperatorSpec instances for property testing. +func DiskAccessOperatorSpecGenerator() gopter.Gen { + if diskAccessOperatorSpecGenerator != nil { + return diskAccessOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskAccessOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskAccessOperatorSpec{}), generators) + + return diskAccessOperatorSpecGenerator +} + func Test_DiskAccess_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -238,6 +293,7 @@ func AddIndependentPropertyGeneratorsForDiskAccess_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForDiskAccess_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDiskAccess_Spec(gens map[string]gopter.Gen) { gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskAccessOperatorSpecGenerator()) } func Test_PrivateEndpointConnection_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen.go b/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen.go index 4809c229bc2..8204271799b 100644 --- a/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen.go +++ b/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (encryptionSet *DiskEncryptionSet) SetConditions(conditions conditions.Cond encryptionSet.Status.Conditions = conditions } +var _ configmaps.Exporter = &DiskEncryptionSet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryptionSet *DiskEncryptionSet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiskEncryptionSet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryptionSet *DiskEncryptionSet) SecretDestinationExpressions() []*core.DestinationExpression { + if encryptionSet.Spec.OperatorSpec == nil { + return nil + } + return encryptionSet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DiskEncryptionSet{} // AzureName returns the Azure name of the resource @@ -150,6 +173,7 @@ type DiskEncryptionSet_Spec struct { FederatedClientIdFromConfig *genruntime.ConfigMapReference `json:"federatedClientIdFromConfig,omitempty" optionalConfigMapPair:"FederatedClientId"` Identity *EncryptionSetIdentity `json:"identity,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *DiskEncryptionSetOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -234,6 +258,14 @@ type ApiError_STATUS struct { Target *string `json:"target,omitempty"` } +// Storage version of v1api20240302.DiskEncryptionSetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskEncryptionSetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240302.EncryptionSetIdentity // The managed identity for the disk encryption set. It should be given permission on the key vault before it can be used // to encrypt disks. diff --git a/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen_test.go b/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen_test.go index 62cc686a481..a757088cfd6 100644 --- a/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen_test.go +++ b/v2/api/compute/v1api20240302/storage/disk_encryption_set_types_gen_test.go @@ -218,6 +218,61 @@ func AddRelatedPropertyGeneratorsForDiskEncryptionSet(gens map[string]gopter.Gen gens["Status"] = DiskEncryptionSet_STATUSGenerator() } +func Test_DiskEncryptionSetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskEncryptionSetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskEncryptionSetOperatorSpec, DiskEncryptionSetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskEncryptionSetOperatorSpec runs a test to see if a specific instance of DiskEncryptionSetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskEncryptionSetOperatorSpec(subject DiskEncryptionSetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskEncryptionSetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskEncryptionSetOperatorSpec instances for property testing - lazily instantiated by +// DiskEncryptionSetOperatorSpecGenerator() +var diskEncryptionSetOperatorSpecGenerator gopter.Gen + +// DiskEncryptionSetOperatorSpecGenerator returns a generator of DiskEncryptionSetOperatorSpec instances for property testing. +func DiskEncryptionSetOperatorSpecGenerator() gopter.Gen { + if diskEncryptionSetOperatorSpecGenerator != nil { + return diskEncryptionSetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskEncryptionSetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskEncryptionSetOperatorSpec{}), generators) + + return diskEncryptionSetOperatorSpecGenerator +} + func Test_DiskEncryptionSet_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -389,6 +444,7 @@ func AddIndependentPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiskEncryptionSet_Spec(gens map[string]gopter.Gen) { gens["ActiveKey"] = gen.PtrOf(KeyForDiskEncryptionSetGenerator()) gens["Identity"] = gen.PtrOf(EncryptionSetIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskEncryptionSetOperatorSpecGenerator()) } func Test_EncryptionSetIdentity_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/compute/v1api20240302/storage/disk_types_gen.go b/v2/api/compute/v1api20240302/storage/disk_types_gen.go index 4cd8e92e615..3a9e83b5f9d 100644 --- a/v2/api/compute/v1api20240302/storage/disk_types_gen.go +++ b/v2/api/compute/v1api20240302/storage/disk_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (disk *Disk) SetConditions(conditions conditions.Conditions) { disk.Status.Conditions = conditions } +var _ configmaps.Exporter = &Disk{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (disk *Disk) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Disk{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (disk *Disk) SecretDestinationExpressions() []*core.DestinationExpression { + if disk.Spec.OperatorSpec == nil { + return nil + } + return disk.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Disk{} // AzureName returns the Azure name of the resource @@ -168,6 +191,7 @@ type Disk_Spec struct { Location *string `json:"location,omitempty"` MaxShares *int `json:"maxShares,omitempty"` NetworkAccessPolicy *string `json:"networkAccessPolicy,omitempty"` + OperatorSpec *DiskOperatorSpec `json:"operatorSpec,omitempty"` OptimizedForFrequentAttach *bool `json:"optimizedForFrequentAttach,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OsType *string `json:"osType,omitempty"` @@ -320,6 +344,14 @@ type CreationData_STATUS struct { UploadSizeBytes *int `json:"uploadSizeBytes,omitempty"` } +// Storage version of v1api20240302.DiskOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiskOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240302.DiskSecurityProfile // Contains the security related information for the resource. type DiskSecurityProfile struct { diff --git a/v2/api/compute/v1api20240302/storage/disk_types_gen_test.go b/v2/api/compute/v1api20240302/storage/disk_types_gen_test.go index 7bf96fff592..41ccaa7d75d 100644 --- a/v2/api/compute/v1api20240302/storage/disk_types_gen_test.go +++ b/v2/api/compute/v1api20240302/storage/disk_types_gen_test.go @@ -246,6 +246,60 @@ func AddRelatedPropertyGeneratorsForDisk(gens map[string]gopter.Gen) { gens["Status"] = Disk_STATUSGenerator() } +func Test_DiskOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiskOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiskOperatorSpec, DiskOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiskOperatorSpec runs a test to see if a specific instance of DiskOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiskOperatorSpec(subject DiskOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiskOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiskOperatorSpec instances for property testing - lazily instantiated by DiskOperatorSpecGenerator() +var diskOperatorSpecGenerator gopter.Gen + +// DiskOperatorSpecGenerator returns a generator of DiskOperatorSpec instances for property testing. +func DiskOperatorSpecGenerator() gopter.Gen { + if diskOperatorSpecGenerator != nil { + return diskOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diskOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiskOperatorSpec{}), generators) + + return diskOperatorSpecGenerator +} + func Test_DiskSecurityProfile_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -703,6 +757,7 @@ func AddRelatedPropertyGeneratorsForDisk_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiskOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["SecurityProfile"] = gen.PtrOf(DiskSecurityProfileGenerator()) gens["Sku"] = gen.PtrOf(DiskSkuGenerator()) diff --git a/v2/api/compute/v1api20240302/storage/snapshot_types_gen.go b/v2/api/compute/v1api20240302/storage/snapshot_types_gen.go index cb6d349bce0..edba4f47160 100644 --- a/v2/api/compute/v1api20240302/storage/snapshot_types_gen.go +++ b/v2/api/compute/v1api20240302/storage/snapshot_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (snapshot *Snapshot) SetConditions(conditions conditions.Conditions) { snapshot.Status.Conditions = conditions } +var _ configmaps.Exporter = &Snapshot{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (snapshot *Snapshot) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Snapshot{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (snapshot *Snapshot) SecretDestinationExpressions() []*core.DestinationExpression { + if snapshot.Spec.OperatorSpec == nil { + return nil + } + return snapshot.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Snapshot{} // AzureName returns the Azure name of the resource @@ -159,6 +182,7 @@ type Snapshot_Spec struct { Incremental *bool `json:"incremental,omitempty"` Location *string `json:"location,omitempty"` NetworkAccessPolicy *string `json:"networkAccessPolicy,omitempty"` + OperatorSpec *SnapshotOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OsType *string `json:"osType,omitempty"` @@ -271,6 +295,14 @@ type CopyCompletionError_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20240302.SnapshotOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SnapshotOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240302.SnapshotSku // The snapshots sku name. Can be Standard_LRS, Premium_LRS, or Standard_ZRS. This is an optional parameter for incremental // snapshot and the default behavior is the SKU will be set to the same sku as the previous snapshot diff --git a/v2/api/compute/v1api20240302/storage/snapshot_types_gen_test.go b/v2/api/compute/v1api20240302/storage/snapshot_types_gen_test.go index cd9b70b37ac..d2e18a66e2e 100644 --- a/v2/api/compute/v1api20240302/storage/snapshot_types_gen_test.go +++ b/v2/api/compute/v1api20240302/storage/snapshot_types_gen_test.go @@ -202,6 +202,61 @@ func AddRelatedPropertyGeneratorsForSnapshot(gens map[string]gopter.Gen) { gens["Status"] = Snapshot_STATUSGenerator() } +func Test_SnapshotOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SnapshotOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSnapshotOperatorSpec, SnapshotOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSnapshotOperatorSpec runs a test to see if a specific instance of SnapshotOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSnapshotOperatorSpec(subject SnapshotOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SnapshotOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SnapshotOperatorSpec instances for property testing - lazily instantiated by +// SnapshotOperatorSpecGenerator() +var snapshotOperatorSpecGenerator gopter.Gen + +// SnapshotOperatorSpecGenerator returns a generator of SnapshotOperatorSpec instances for property testing. +func SnapshotOperatorSpecGenerator() gopter.Gen { + if snapshotOperatorSpecGenerator != nil { + return snapshotOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + snapshotOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SnapshotOperatorSpec{}), generators) + + return snapshotOperatorSpecGenerator +} + func Test_SnapshotSku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -519,6 +574,7 @@ func AddRelatedPropertyGeneratorsForSnapshot_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionGenerator()) gens["EncryptionSettingsCollection"] = gen.PtrOf(EncryptionSettingsCollectionGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SnapshotOperatorSpecGenerator()) gens["PurchasePlan"] = gen.PtrOf(PurchasePlanGenerator()) gens["SecurityProfile"] = gen.PtrOf(DiskSecurityProfileGenerator()) gens["Sku"] = gen.PtrOf(SnapshotSkuGenerator()) diff --git a/v2/api/compute/v1api20240302/storage/structure.txt b/v2/api/compute/v1api20240302/storage/structure.txt index 2012a063a66..e189a1d7361 100644 --- a/v2/api/compute/v1api20240302/storage/structure.txt +++ b/v2/api/compute/v1api20240302/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2024-03-02" Disk: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (32 properties) +├── Spec: Object (33 properties) │ ├── AzureName: string │ ├── BurstingEnabled: *bool │ ├── CompletionPercent: *float64 @@ -70,6 +70,10 @@ Disk: Resource │ ├── Location: *string │ ├── MaxShares: *int │ ├── NetworkAccessPolicy: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OptimizedForFrequentAttach: *bool │ ├── OriginalVersion: string │ ├── OsType: *string @@ -211,13 +215,17 @@ Disk: Resource └── Zones: string[] DiskAccess: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (3 properties) │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Type: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -241,7 +249,7 @@ DiskAccess: Resource └── Type: *string DiskEncryptionSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── ActiveKey: *Object (4 properties) │ │ ├── KeyUrl: *string │ │ ├── KeyUrlFromConfig: *genruntime.ConfigMapReference @@ -260,6 +268,10 @@ DiskEncryptionSet: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -315,7 +327,7 @@ DiskEncryptionSet: Resource └── Type: *string Snapshot: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (26 properties) +├── Spec: Object (27 properties) │ ├── AzureName: string │ ├── CompletionPercent: *float64 │ ├── CopyCompletionError: *Object (3 properties) @@ -380,6 +392,10 @@ Snapshot: Resource │ ├── Incremental: *bool │ ├── Location: *string │ ├── NetworkAccessPolicy: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsType: *string │ ├── Owner: *genruntime.KnownResourceReference diff --git a/v2/api/compute/v1api20240302/storage/zz_generated.deepcopy.go b/v2/api/compute/v1api20240302/storage/zz_generated.deepcopy.go index 86a104b11bb..afdc6b0cc02 100644 --- a/v2/api/compute/v1api20240302/storage/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20240302/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -420,6 +421,50 @@ func (in *DiskAccessList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskAccessOperatorSpec) DeepCopyInto(out *DiskAccessOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskAccessOperatorSpec. +func (in *DiskAccessOperatorSpec) DeepCopy() *DiskAccessOperatorSpec { + if in == nil { + return nil + } + out := new(DiskAccessOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskAccess_STATUS) DeepCopyInto(out *DiskAccess_STATUS) { *out = *in @@ -511,6 +556,11 @@ func (in *DiskAccess_Spec) DeepCopyInto(out *DiskAccess_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskAccessOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -601,6 +651,50 @@ func (in *DiskEncryptionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskEncryptionSetOperatorSpec) DeepCopyInto(out *DiskEncryptionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSetOperatorSpec. +func (in *DiskEncryptionSetOperatorSpec) DeepCopy() *DiskEncryptionSetOperatorSpec { + if in == nil { + return nil + } + out := new(DiskEncryptionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSet_STATUS) DeepCopyInto(out *DiskEncryptionSet_STATUS) { *out = *in @@ -737,6 +831,11 @@ func (in *DiskEncryptionSet_Spec) DeepCopyInto(out *DiskEncryptionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskEncryptionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -805,6 +904,50 @@ func (in *DiskList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskOperatorSpec) DeepCopyInto(out *DiskOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskOperatorSpec. +func (in *DiskOperatorSpec) DeepCopy() *DiskOperatorSpec { + if in == nil { + return nil + } + out := new(DiskOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskSecurityProfile) DeepCopyInto(out *DiskSecurityProfile) { *out = *in @@ -1259,6 +1402,11 @@ func (in *Disk_Spec) DeepCopyInto(out *Disk_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OptimizedForFrequentAttach != nil { in, out := &in.OptimizedForFrequentAttach, &out.OptimizedForFrequentAttach *out = new(bool) @@ -2257,6 +2405,50 @@ func (in *SnapshotList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotOperatorSpec) DeepCopyInto(out *SnapshotOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotOperatorSpec. +func (in *SnapshotOperatorSpec) DeepCopy() *SnapshotOperatorSpec { + if in == nil { + return nil + } + out := new(SnapshotOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SnapshotSku) DeepCopyInto(out *SnapshotSku) { *out = *in @@ -2575,6 +2767,11 @@ func (in *Snapshot_Spec) DeepCopyInto(out *Snapshot_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SnapshotOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(string) diff --git a/v2/api/compute/v1api20240302/structure.txt b/v2/api/compute/v1api20240302/structure.txt index 0af502df369..0bb0d221244 100644 --- a/v2/api/compute/v1api20240302/structure.txt +++ b/v2/api/compute/v1api20240302/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2024-03-02" Disk: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (30 properties) +├── Spec: Object (31 properties) │ ├── AzureName: string │ ├── BurstingEnabled: *bool │ ├── CompletionPercent: *float64 @@ -83,6 +83,9 @@ Disk: Resource │ │ ├── "AllowAll" │ │ ├── "AllowPrivate" │ │ └── "DenyAll" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OptimizedForFrequentAttach: *bool │ ├── OsType: *Enum (2 values) │ │ ├── "Linux" @@ -268,13 +271,16 @@ Disk: Resource └── Zones: string[] DiskAccess: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── ExtendedLocation: *Object (2 properties) │ │ ├── Name: *string │ │ └── Type: *Enum (1 value) │ │ └── "EdgeZone" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (10 properties) @@ -294,7 +300,7 @@ DiskAccess: Resource └── Type: *string DiskEncryptionSet: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── ActiveKey: *Object (3 properties) │ │ ├── KeyUrl: *string │ │ ├── KeyUrlFromConfig: *genruntime.ConfigMapReference @@ -316,6 +322,9 @@ DiskEncryptionSet: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RotationToLatestKeyVersionEnabled: *bool │ └── Tags: map[string]string @@ -366,7 +375,7 @@ DiskEncryptionSet: Resource └── Type: *string Snapshot: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (24 properties) +├── Spec: Object (25 properties) │ ├── AzureName: string │ ├── CompletionPercent: *float64 │ ├── CopyCompletionError: *Object (2 properties) @@ -452,6 +461,9 @@ Snapshot: Resource │ │ ├── "AllowAll" │ │ ├── "AllowPrivate" │ │ └── "DenyAll" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsType: *Enum (2 values) │ │ ├── "Linux" │ │ └── "Windows" diff --git a/v2/api/compute/v1api20240302/zz_generated.deepcopy.go b/v2/api/compute/v1api20240302/zz_generated.deepcopy.go index 686e02bdb2c..a01d68a0b95 100644 --- a/v2/api/compute/v1api20240302/zz_generated.deepcopy.go +++ b/v2/api/compute/v1api20240302/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20240302 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -378,6 +379,43 @@ func (in *DiskAccessList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskAccessOperatorSpec) DeepCopyInto(out *DiskAccessOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskAccessOperatorSpec. +func (in *DiskAccessOperatorSpec) DeepCopy() *DiskAccessOperatorSpec { + if in == nil { + return nil + } + out := new(DiskAccessOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskAccess_STATUS) DeepCopyInto(out *DiskAccess_STATUS) { *out = *in @@ -462,6 +500,11 @@ func (in *DiskAccess_Spec) DeepCopyInto(out *DiskAccess_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskAccessOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -545,6 +588,43 @@ func (in *DiskEncryptionSetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskEncryptionSetOperatorSpec) DeepCopyInto(out *DiskEncryptionSetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSetOperatorSpec. +func (in *DiskEncryptionSetOperatorSpec) DeepCopy() *DiskEncryptionSetOperatorSpec { + if in == nil { + return nil + } + out := new(DiskEncryptionSetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSet_STATUS) DeepCopyInto(out *DiskEncryptionSet_STATUS) { *out = *in @@ -674,6 +754,11 @@ func (in *DiskEncryptionSet_Spec) DeepCopyInto(out *DiskEncryptionSet_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskEncryptionSetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -735,6 +820,43 @@ func (in *DiskList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskOperatorSpec) DeepCopyInto(out *DiskOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskOperatorSpec. +func (in *DiskOperatorSpec) DeepCopy() *DiskOperatorSpec { + if in == nil { + return nil + } + out := new(DiskOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskSecurityProfile) DeepCopyInto(out *DiskSecurityProfile) { *out = *in @@ -1154,6 +1276,11 @@ func (in *Disk_Spec) DeepCopyInto(out *Disk_Spec) { *out = new(NetworkAccessPolicy) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiskOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OptimizedForFrequentAttach != nil { in, out := &in.OptimizedForFrequentAttach, &out.OptimizedForFrequentAttach *out = new(bool) @@ -1968,6 +2095,43 @@ func (in *SnapshotList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SnapshotOperatorSpec) DeepCopyInto(out *SnapshotOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotOperatorSpec. +func (in *SnapshotOperatorSpec) DeepCopy() *SnapshotOperatorSpec { + if in == nil { + return nil + } + out := new(SnapshotOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SnapshotSku) DeepCopyInto(out *SnapshotSku) { *out = *in @@ -2265,6 +2429,11 @@ func (in *Snapshot_Spec) DeepCopyInto(out *Snapshot_Spec) { *out = new(NetworkAccessPolicy) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SnapshotOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(SnapshotProperties_OsType) diff --git a/v2/api/containerinstance/v1api20211001/container_group_types_gen.go b/v2/api/containerinstance/v1api20211001/container_group_types_gen.go index 90b3d12af5d..90c9d73200c 100644 --- a/v2/api/containerinstance/v1api20211001/container_group_types_gen.go +++ b/v2/api/containerinstance/v1api20211001/container_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (group *ContainerGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the ContainerGroup resource func (group *ContainerGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &ContainerGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ContainerGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ContainerGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ContainerGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ContainerGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (group *ContainerGroup) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (group *ContainerGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (group *ContainerGroup) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *ContainerGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (group *ContainerGroup) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *ContainerGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *ContainerGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ContainerGroup) @@ -364,6 +409,10 @@ type ContainerGroup_Spec struct { // Location: The resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ContainerGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // OsType: The operating system type required by the containers in the container group. OsType *ContainerGroup_Properties_OsType_Spec `json:"osType,omitempty"` @@ -667,6 +716,8 @@ func (group *ContainerGroup_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne group.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OsType": // copying flattened property: if typedInput.Properties != nil { @@ -922,6 +973,18 @@ func (group *ContainerGroup_Spec) AssignProperties_From_ContainerGroup_Spec(sour // Location group.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ContainerGroupOperatorSpec + err := operatorSpec.AssignProperties_From_ContainerGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ContainerGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // OsType if source.OsType != nil { osType := *source.OsType @@ -1128,6 +1191,18 @@ func (group *ContainerGroup_Spec) AssignProperties_To_ContainerGroup_Spec(destin // Location destination.Location = genruntime.ClonePointerToString(group.Location) + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.ContainerGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_ContainerGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ContainerGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -3897,6 +3972,110 @@ func (identity *ContainerGroupIdentity_STATUS) AssignProperties_To_ContainerGrou return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ContainerGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ContainerGroupOperatorSpec populates our ContainerGroupOperatorSpec from the provided source ContainerGroupOperatorSpec +func (operator *ContainerGroupOperatorSpec) AssignProperties_From_ContainerGroupOperatorSpec(source *storage.ContainerGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ContainerGroupOperatorSpec populates the provided destination ContainerGroupOperatorSpec from our ContainerGroupOperatorSpec +func (operator *ContainerGroupOperatorSpec) AssignProperties_To_ContainerGroupOperatorSpec(destination *storage.ContainerGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The container group SKU. // +kubebuilder:validation:Enum={"Dedicated","Standard"} type ContainerGroupSku string diff --git a/v2/api/containerinstance/v1api20211001/container_group_types_gen_test.go b/v2/api/containerinstance/v1api20211001/container_group_types_gen_test.go index 719739b2b66..9d1f06154c3 100644 --- a/v2/api/containerinstance/v1api20211001/container_group_types_gen_test.go +++ b/v2/api/containerinstance/v1api20211001/container_group_types_gen_test.go @@ -1155,6 +1155,103 @@ func AddRelatedPropertyGeneratorsForContainerGroupIdentity_STATUS(gens map[strin UserAssignedIdentities_STATUSGenerator()) } +func Test_ContainerGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ContainerGroupOperatorSpec to ContainerGroupOperatorSpec via AssignProperties_To_ContainerGroupOperatorSpec & AssignProperties_From_ContainerGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForContainerGroupOperatorSpec, ContainerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForContainerGroupOperatorSpec tests if a specific instance of ContainerGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForContainerGroupOperatorSpec(subject ContainerGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ContainerGroupOperatorSpec + err := copied.AssignProperties_To_ContainerGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ContainerGroupOperatorSpec + err = actual.AssignProperties_From_ContainerGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ContainerGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ContainerGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForContainerGroupOperatorSpec, ContainerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForContainerGroupOperatorSpec runs a test to see if a specific instance of ContainerGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForContainerGroupOperatorSpec(subject ContainerGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ContainerGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ContainerGroupOperatorSpec instances for property testing - lazily instantiated by +// ContainerGroupOperatorSpecGenerator() +var containerGroupOperatorSpecGenerator gopter.Gen + +// ContainerGroupOperatorSpecGenerator returns a generator of ContainerGroupOperatorSpec instances for property testing. +func ContainerGroupOperatorSpecGenerator() gopter.Gen { + if containerGroupOperatorSpecGenerator != nil { + return containerGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + containerGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ContainerGroupOperatorSpec{}), generators) + + return containerGroupOperatorSpecGenerator +} + func Test_ContainerGroupSubnetId_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1747,6 +1844,7 @@ func AddRelatedPropertyGeneratorsForContainerGroup_Spec(gens map[string]gopter.G gens["ImageRegistryCredentials"] = gen.SliceOf(ImageRegistryCredentialGenerator()) gens["InitContainers"] = gen.SliceOf(InitContainerDefinitionGenerator()) gens["IpAddress"] = gen.PtrOf(IpAddressGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ContainerGroupOperatorSpecGenerator()) gens["SubnetIds"] = gen.SliceOf(ContainerGroupSubnetIdGenerator()) gens["Volumes"] = gen.SliceOf(VolumeGenerator()) } diff --git a/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen.go b/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen.go index ac8a2754d91..ef32ffc6f00 100644 --- a/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen.go +++ b/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (group *ContainerGroup) SetConditions(conditions conditions.Conditions) { group.Status.Conditions = conditions } +var _ configmaps.Exporter = &ContainerGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ContainerGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ContainerGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ContainerGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ContainerGroup{} // AzureName returns the Azure name of the resource @@ -149,18 +172,19 @@ const APIVersion_Value = APIVersion("2021-10-01") type ContainerGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Containers []Container `json:"containers,omitempty"` - Diagnostics *ContainerGroupDiagnostics `json:"diagnostics,omitempty"` - DnsConfig *DnsConfiguration `json:"dnsConfig,omitempty"` - EncryptionProperties *EncryptionProperties `json:"encryptionProperties,omitempty"` - Identity *ContainerGroupIdentity `json:"identity,omitempty"` - ImageRegistryCredentials []ImageRegistryCredential `json:"imageRegistryCredentials,omitempty"` - InitContainers []InitContainerDefinition `json:"initContainers,omitempty"` - IpAddress *IpAddress `json:"ipAddress,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsType *string `json:"osType,omitempty"` + AzureName string `json:"azureName,omitempty"` + Containers []Container `json:"containers,omitempty"` + Diagnostics *ContainerGroupDiagnostics `json:"diagnostics,omitempty"` + DnsConfig *DnsConfiguration `json:"dnsConfig,omitempty"` + EncryptionProperties *EncryptionProperties `json:"encryptionProperties,omitempty"` + Identity *ContainerGroupIdentity `json:"identity,omitempty"` + ImageRegistryCredentials []ImageRegistryCredential `json:"imageRegistryCredentials,omitempty"` + InitContainers []InitContainerDefinition `json:"initContainers,omitempty"` + IpAddress *IpAddress `json:"ipAddress,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *ContainerGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -314,6 +338,14 @@ type ContainerGroupIdentity_STATUS struct { UserAssignedIdentities map[string]UserAssignedIdentities_STATUS `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20211001.ContainerGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ContainerGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211001.ContainerGroupSubnetId // Container group subnet information. type ContainerGroupSubnetId struct { diff --git a/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen_test.go b/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen_test.go index 46d56a4dace..3cd44845ecf 100644 --- a/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen_test.go +++ b/v2/api/containerinstance/v1api20211001/storage/container_group_types_gen_test.go @@ -683,6 +683,61 @@ func AddRelatedPropertyGeneratorsForContainerGroupIdentity_STATUS(gens map[strin UserAssignedIdentities_STATUSGenerator()) } +func Test_ContainerGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ContainerGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForContainerGroupOperatorSpec, ContainerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForContainerGroupOperatorSpec runs a test to see if a specific instance of ContainerGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForContainerGroupOperatorSpec(subject ContainerGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ContainerGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ContainerGroupOperatorSpec instances for property testing - lazily instantiated by +// ContainerGroupOperatorSpecGenerator() +var containerGroupOperatorSpecGenerator gopter.Gen + +// ContainerGroupOperatorSpecGenerator returns a generator of ContainerGroupOperatorSpec instances for property testing. +func ContainerGroupOperatorSpecGenerator() gopter.Gen { + if containerGroupOperatorSpecGenerator != nil { + return containerGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + containerGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ContainerGroupOperatorSpec{}), generators) + + return containerGroupOperatorSpecGenerator +} + func Test_ContainerGroupSubnetId_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1066,6 +1121,7 @@ func AddRelatedPropertyGeneratorsForContainerGroup_Spec(gens map[string]gopter.G gens["ImageRegistryCredentials"] = gen.SliceOf(ImageRegistryCredentialGenerator()) gens["InitContainers"] = gen.SliceOf(InitContainerDefinitionGenerator()) gens["IpAddress"] = gen.PtrOf(IpAddressGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ContainerGroupOperatorSpecGenerator()) gens["SubnetIds"] = gen.SliceOf(ContainerGroupSubnetIdGenerator()) gens["Volumes"] = gen.SliceOf(VolumeGenerator()) } diff --git a/v2/api/containerinstance/v1api20211001/storage/structure.txt b/v2/api/containerinstance/v1api20211001/storage/structure.txt index 107f6048b3a..cde651fb1a1 100644 --- a/v2/api/containerinstance/v1api20211001/storage/structure.txt +++ b/v2/api/containerinstance/v1api20211001/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-10-01" ContainerGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (20 properties) +├── Spec: Object (21 properties) │ ├── AzureName: string │ ├── Containers: Object (10 properties)[] │ │ ├── Command: string[] @@ -140,6 +140,10 @@ ContainerGroup: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Type: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OsType: *string │ ├── Owner: *genruntime.KnownResourceReference diff --git a/v2/api/containerinstance/v1api20211001/storage/zz_generated.deepcopy.go b/v2/api/containerinstance/v1api20211001/storage/zz_generated.deepcopy.go index b1af54a68a1..d6e8a5efc67 100644 --- a/v2/api/containerinstance/v1api20211001/storage/zz_generated.deepcopy.go +++ b/v2/api/containerinstance/v1api20211001/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -418,6 +419,50 @@ func (in *ContainerGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerGroupOperatorSpec) DeepCopyInto(out *ContainerGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerGroupOperatorSpec. +func (in *ContainerGroupOperatorSpec) DeepCopy() *ContainerGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ContainerGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ContainerGroupSubnetId) DeepCopyInto(out *ContainerGroupSubnetId) { *out = *in @@ -716,6 +761,11 @@ func (in *ContainerGroup_Spec) DeepCopyInto(out *ContainerGroup_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ContainerGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(string) diff --git a/v2/api/containerinstance/v1api20211001/structure.txt b/v2/api/containerinstance/v1api20211001/structure.txt index 15c9c404eb1..7370e1bc980 100644 --- a/v2/api/containerinstance/v1api20211001/structure.txt +++ b/v2/api/containerinstance/v1api20211001/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-10-01" ContainerGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AzureName: string │ ├── Containers: Object (9 properties)[] │ │ ├── Command: string[] @@ -138,6 +138,9 @@ ContainerGroup: Resource │ │ ├── "Private" │ │ └── "Public" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OsType: *Enum (2 values) │ │ ├── "Linux" │ │ └── "Windows" diff --git a/v2/api/containerinstance/v1api20211001/zz_generated.deepcopy.go b/v2/api/containerinstance/v1api20211001/zz_generated.deepcopy.go index 3e3256e9527..2b54c9efa27 100644 --- a/v2/api/containerinstance/v1api20211001/zz_generated.deepcopy.go +++ b/v2/api/containerinstance/v1api20211001/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20211001 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -353,6 +354,43 @@ func (in *ContainerGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerGroupOperatorSpec) DeepCopyInto(out *ContainerGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerGroupOperatorSpec. +func (in *ContainerGroupOperatorSpec) DeepCopy() *ContainerGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ContainerGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ContainerGroupSubnetId) DeepCopyInto(out *ContainerGroupSubnetId) { *out = *in @@ -623,6 +661,11 @@ func (in *ContainerGroup_Spec) DeepCopyInto(out *ContainerGroup_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ContainerGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OsType != nil { in, out := &in.OsType, &out.OsType *out = new(ContainerGroup_Properties_OsType_Spec) diff --git a/v2/api/containerregistry/v1api20210901/registry_types_gen.go b/v2/api/containerregistry/v1api20210901/registry_types_gen.go index 384b732221b..f152c92fb4c 100644 --- a/v2/api/containerregistry/v1api20210901/registry_types_gen.go +++ b/v2/api/containerregistry/v1api20210901/registry_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (registry *Registry) defaultAzureName() { // defaultImpl applies the code generated defaults to the Registry resource func (registry *Registry) defaultImpl() { registry.defaultAzureName() } +var _ configmaps.Exporter = &Registry{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (registry *Registry) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Registry{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (registry *Registry) SecretDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Registry{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (registry *Registry) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (registry *Registry) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){registry.validateResourceReferences, registry.validateOwnerReference} + return []func() (admission.Warnings, error){registry.validateResourceReferences, registry.validateOwnerReference, registry.validateSecretDestinations, registry.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (registry *Registry) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return registry.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return registry.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return registry.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (registry *Registry) validateConfigMapDestinations() (admission.Warnings, error) { + if registry.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(registry, nil, registry.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (registry *Registry) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (registry *Registry) validateSecretDestinations() (admission.Warnings, error) { + if registry.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(registry, nil, registry.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (registry *Registry) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Registry) @@ -360,6 +405,10 @@ type Registry_Spec struct { // NetworkRuleSet: The network rule set for a container registry. NetworkRuleSet *NetworkRuleSet `json:"networkRuleSet,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RegistryOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -582,6 +631,8 @@ func (registry *Registry_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": registry.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -767,6 +818,18 @@ func (registry *Registry_Spec) AssignProperties_From_Registry_Spec(source *stora registry.NetworkRuleSet = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RegistryOperatorSpec + err := operatorSpec.AssignProperties_From_RegistryOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RegistryOperatorSpec() to populate field OperatorSpec") + } + registry.OperatorSpec = &operatorSpec + } else { + registry.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -895,6 +958,18 @@ func (registry *Registry_Spec) AssignProperties_To_Registry_Spec(destination *st destination.NetworkRuleSet = nil } + // OperatorSpec + if registry.OperatorSpec != nil { + var operatorSpec storage.RegistryOperatorSpec + err := registry.OperatorSpec.AssignProperties_To_RegistryOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RegistryOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = registry.OriginalVersion() @@ -3331,6 +3406,110 @@ func (connection *PrivateEndpointConnection_STATUS) AssignProperties_To_PrivateE return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RegistryOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RegistryOperatorSpec populates our RegistryOperatorSpec from the provided source RegistryOperatorSpec +func (operator *RegistryOperatorSpec) AssignProperties_From_RegistryOperatorSpec(source *storage.RegistryOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RegistryOperatorSpec populates the provided destination RegistryOperatorSpec from our RegistryOperatorSpec +func (operator *RegistryOperatorSpec) AssignProperties_To_RegistryOperatorSpec(destination *storage.RegistryOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"AzureServices","None"} type RegistryProperties_NetworkRuleBypassOptions string diff --git a/v2/api/containerregistry/v1api20210901/registry_types_gen_test.go b/v2/api/containerregistry/v1api20210901/registry_types_gen_test.go index 0e712c12cfa..25127c81af9 100644 --- a/v2/api/containerregistry/v1api20210901/registry_types_gen_test.go +++ b/v2/api/containerregistry/v1api20210901/registry_types_gen_test.go @@ -2016,6 +2016,103 @@ func AddRelatedPropertyGeneratorsForRegistry(gens map[string]gopter.Gen) { gens["Status"] = Registry_STATUSGenerator() } +func Test_RegistryOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RegistryOperatorSpec to RegistryOperatorSpec via AssignProperties_To_RegistryOperatorSpec & AssignProperties_From_RegistryOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRegistryOperatorSpec, RegistryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRegistryOperatorSpec tests if a specific instance of RegistryOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRegistryOperatorSpec(subject RegistryOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RegistryOperatorSpec + err := copied.AssignProperties_To_RegistryOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RegistryOperatorSpec + err = actual.AssignProperties_From_RegistryOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RegistryOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RegistryOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRegistryOperatorSpec, RegistryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRegistryOperatorSpec runs a test to see if a specific instance of RegistryOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRegistryOperatorSpec(subject RegistryOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RegistryOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RegistryOperatorSpec instances for property testing - lazily instantiated by +// RegistryOperatorSpecGenerator() +var registryOperatorSpecGenerator gopter.Gen + +// RegistryOperatorSpecGenerator returns a generator of RegistryOperatorSpec instances for property testing. +func RegistryOperatorSpecGenerator() gopter.Gen { + if registryOperatorSpecGenerator != nil { + return registryOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + registryOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RegistryOperatorSpec{}), generators) + + return registryOperatorSpecGenerator +} + func Test_Registry_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2285,6 +2382,7 @@ func AddRelatedPropertyGeneratorsForRegistry_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionPropertyGenerator()) gens["Identity"] = gen.PtrOf(IdentityPropertiesGenerator()) gens["NetworkRuleSet"] = gen.PtrOf(NetworkRuleSetGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RegistryOperatorSpecGenerator()) gens["Policies"] = gen.PtrOf(PoliciesGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/containerregistry/v1api20210901/storage/registry_types_gen.go b/v2/api/containerregistry/v1api20210901/storage/registry_types_gen.go index a9b446fa138..91c16ad5e42 100644 --- a/v2/api/containerregistry/v1api20210901/storage/registry_types_gen.go +++ b/v2/api/containerregistry/v1api20210901/storage/registry_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (registry *Registry) SetConditions(conditions conditions.Conditions) { registry.Status.Conditions = conditions } +var _ configmaps.Exporter = &Registry{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (registry *Registry) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Registry{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (registry *Registry) SecretDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Registry{} // AzureName returns the Azure name of the resource @@ -150,14 +173,15 @@ type Registry_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DataEndpointEnabled *bool `json:"dataEndpointEnabled,omitempty"` - Encryption *EncryptionProperty `json:"encryption,omitempty"` - Identity *IdentityProperties `json:"identity,omitempty"` - Location *string `json:"location,omitempty"` - NetworkRuleBypassOptions *string `json:"networkRuleBypassOptions,omitempty"` - NetworkRuleSet *NetworkRuleSet `json:"networkRuleSet,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DataEndpointEnabled *bool `json:"dataEndpointEnabled,omitempty"` + Encryption *EncryptionProperty `json:"encryption,omitempty"` + Identity *IdentityProperties `json:"identity,omitempty"` + Location *string `json:"location,omitempty"` + NetworkRuleBypassOptions *string `json:"networkRuleBypassOptions,omitempty"` + NetworkRuleSet *NetworkRuleSet `json:"networkRuleSet,omitempty"` + OperatorSpec *RegistryOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -318,6 +342,14 @@ type PrivateEndpointConnection_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20210901.RegistryOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RegistryOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210901.Sku // The SKU of a container registry. type Sku struct { diff --git a/v2/api/containerregistry/v1api20210901/storage/registry_types_gen_test.go b/v2/api/containerregistry/v1api20210901/storage/registry_types_gen_test.go index 4f465e93a50..412dd9f7ebb 100644 --- a/v2/api/containerregistry/v1api20210901/storage/registry_types_gen_test.go +++ b/v2/api/containerregistry/v1api20210901/storage/registry_types_gen_test.go @@ -1208,6 +1208,61 @@ func AddRelatedPropertyGeneratorsForRegistry(gens map[string]gopter.Gen) { gens["Status"] = Registry_STATUSGenerator() } +func Test_RegistryOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RegistryOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRegistryOperatorSpec, RegistryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRegistryOperatorSpec runs a test to see if a specific instance of RegistryOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRegistryOperatorSpec(subject RegistryOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RegistryOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RegistryOperatorSpec instances for property testing - lazily instantiated by +// RegistryOperatorSpecGenerator() +var registryOperatorSpecGenerator gopter.Gen + +// RegistryOperatorSpecGenerator returns a generator of RegistryOperatorSpec instances for property testing. +func RegistryOperatorSpecGenerator() gopter.Gen { + if registryOperatorSpecGenerator != nil { + return registryOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + registryOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RegistryOperatorSpec{}), generators) + + return registryOperatorSpecGenerator +} + func Test_Registry_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1388,6 +1443,7 @@ func AddRelatedPropertyGeneratorsForRegistry_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionPropertyGenerator()) gens["Identity"] = gen.PtrOf(IdentityPropertiesGenerator()) gens["NetworkRuleSet"] = gen.PtrOf(NetworkRuleSetGenerator()) + gens["OperatorSpec"] = gen.PtrOf(RegistryOperatorSpecGenerator()) gens["Policies"] = gen.PtrOf(PoliciesGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/containerregistry/v1api20210901/storage/structure.txt b/v2/api/containerregistry/v1api20210901/storage/structure.txt index a40cfdd1898..2dfcad2fa05 100644 --- a/v2/api/containerregistry/v1api20210901/storage/structure.txt +++ b/v2/api/containerregistry/v1api20210901/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-09-01" Registry: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AdminUserEnabled: *bool │ ├── AzureName: string │ ├── DataEndpointEnabled: *bool @@ -33,6 +33,10 @@ Registry: Resource │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── Value: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Policies: *Object (5 properties) diff --git a/v2/api/containerregistry/v1api20210901/storage/zz_generated.deepcopy.go b/v2/api/containerregistry/v1api20210901/storage/zz_generated.deepcopy.go index 4678f1b9bc1..033dab7796b 100644 --- a/v2/api/containerregistry/v1api20210901/storage/zz_generated.deepcopy.go +++ b/v2/api/containerregistry/v1api20210901/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -656,6 +657,50 @@ func (in *RegistryList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryOperatorSpec) DeepCopyInto(out *RegistryOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryOperatorSpec. +func (in *RegistryOperatorSpec) DeepCopy() *RegistryOperatorSpec { + if in == nil { + return nil + } + out := new(RegistryOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Registry_STATUS) DeepCopyInto(out *Registry_STATUS) { *out = *in @@ -837,6 +882,11 @@ func (in *Registry_Spec) DeepCopyInto(out *Registry_Spec) { *out = new(NetworkRuleSet) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RegistryOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerregistry/v1api20210901/structure.txt b/v2/api/containerregistry/v1api20210901/structure.txt index 42d47dedc9d..65e8ecfe94f 100644 --- a/v2/api/containerregistry/v1api20210901/structure.txt +++ b/v2/api/containerregistry/v1api20210901/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-09-01" Registry: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AdminUserEnabled: *bool │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 50 @@ -41,6 +41,9 @@ Registry: Resource │ │ ├── Action: *Enum (1 value) │ │ │ └── "Allow" │ │ └── Value: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Policies: *Object (4 properties) │ │ ├── ExportPolicy: *Object (1 property) diff --git a/v2/api/containerregistry/v1api20210901/zz_generated.deepcopy.go b/v2/api/containerregistry/v1api20210901/zz_generated.deepcopy.go index e5445b078e0..6ccfc67c9e8 100644 --- a/v2/api/containerregistry/v1api20210901/zz_generated.deepcopy.go +++ b/v2/api/containerregistry/v1api20210901/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210901 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -535,6 +536,43 @@ func (in *RegistryList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RegistryOperatorSpec) DeepCopyInto(out *RegistryOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryOperatorSpec. +func (in *RegistryOperatorSpec) DeepCopy() *RegistryOperatorSpec { + if in == nil { + return nil + } + out := new(RegistryOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Registry_STATUS) DeepCopyInto(out *Registry_STATUS) { *out = *in @@ -709,6 +747,11 @@ func (in *Registry_Spec) DeepCopyInto(out *Registry_Spec) { *out = new(NetworkRuleSet) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RegistryOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20210501/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20210501/managed_cluster_types_gen.go index 8f248ab2662..49bfd9efdc3 100644 --- a/v2/api/containerservice/v1api20210501/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20210501/managed_cluster_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -103,6 +105,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedCluster{} // AzureName returns the Azure name of the resource @@ -210,7 +232,7 @@ func (cluster *ManagedCluster) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (cluster *ManagedCluster) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){cluster.validateResourceReferences, cluster.validateOwnerReference, cluster.validateSecretDestinations} + return []func() (admission.Warnings, error){cluster.validateResourceReferences, cluster.validateOwnerReference, cluster.validateSecretDestinations, cluster.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (cluster *ManagedCluster) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return cluster.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return cluster.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnings, error) { + if cluster.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(cluster, nil, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,14 +286,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -7235,6 +7268,12 @@ func (identity *ManagedClusterIdentity_STATUS) AssignProperties_To_ManagedCluste // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -7242,6 +7281,42 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -7263,6 +7338,42 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen.go index c7ba91d560e..c4fa17e0e4f 100644 --- a/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -399,6 +444,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: As a best practice, you should upgrade all node pools in an AKS cluster to the same Kubernetes // version. The node pool version must have the same major version as the control plane. The node pool minor version must // be within two minor versions of the control plane version. The node pool version cannot be greater than the control @@ -887,6 +936,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1213,6 +1264,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -1460,6 +1523,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -3713,6 +3788,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Ephemeral","Managed"} type OSDiskType string diff --git a/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen_test.go index 82b1537f4fd..967206c60b3 100644 --- a/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20210501/managed_clusters_agent_pool_types_gen_test.go @@ -834,6 +834,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210501s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1151,6 +1248,7 @@ func AddIndependentPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[s func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[string]gopter.Gen) { gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20210501/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20210501/storage/managed_cluster_types_gen.go index 70d9350e125..46d5f17c956 100644 --- a/v2/api/containerservice/v1api20210501/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20210501/storage/managed_cluster_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20230201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -75,6 +78,26 @@ func (cluster *ManagedCluster) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedCluster{} // AzureName returns the Azure name of the resource @@ -5285,8 +5308,10 @@ func (identity *ManagedClusterIdentity_STATUS) AssignProperties_To_ManagedCluste // Storage version of v1api20210501.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec @@ -5294,6 +5319,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { propertyBag.Add("ConfigMaps", *source.ConfigMaps) @@ -5301,6 +5344,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster propertyBag.Remove("ConfigMaps") } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -5338,6 +5399,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if propertyBag.Contains("ConfigMaps") { var configMap storage.ManagedClusterOperatorConfigMaps @@ -5351,6 +5430,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen.go index d9bbc30fe9e..ce24a654335 100644 --- a/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20230201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (pool *ManagedClustersAgentPool) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -269,14 +292,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixIDReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixIDReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixIDReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixIDReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixIDReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -490,6 +514,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -800,6 +836,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -2237,6 +2285,136 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Storage version of v1api20210501.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForAgentPoolUpgradeSettings interface { AssignPropertiesFrom(src *storage.AgentPoolUpgradeSettings) error AssignPropertiesTo(dst *storage.AgentPoolUpgradeSettings) error @@ -2267,6 +2445,11 @@ type augmentConversionForLinuxOSConfig_STATUS interface { AssignPropertiesTo(dst *storage.LinuxOSConfig_STATUS) error } +type augmentConversionForManagedClustersAgentPoolOperatorSpec interface { + AssignPropertiesFrom(src *storage.ManagedClustersAgentPoolOperatorSpec) error + AssignPropertiesTo(dst *storage.ManagedClustersAgentPoolOperatorSpec) error +} + // Storage version of v1api20210501.SysctlConfig type SysctlConfig struct { FsAioMaxNr *int `json:"fsAioMaxNr,omitempty"` diff --git a/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen_test.go index b230c3efcca..ca2bb689417 100644 --- a/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20210501/storage/managed_clusters_agent_pool_types_gen_test.go @@ -834,6 +834,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230201s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1140,6 +1237,7 @@ func AddIndependentPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[s func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[string]gopter.Gen) { gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20210501/storage/structure.txt b/v2/api/containerservice/v1api20210501/storage/structure.txt index 74770674038..e8bf0c92c73 100644 --- a/v2/api/containerservice/v1api20210501/storage/structure.txt +++ b/v2/api/containerservice/v1api20210501/storage/structure.txt @@ -201,8 +201,10 @@ ManagedCluster: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── ServiceCidr: *string │ ├── NodeResourceGroup: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -529,7 +531,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20210501.ManagedCluster -├── Spec: Object (37 properties) +├── Spec: Object (38 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── Count: *int @@ -595,6 +597,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixIDReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -770,6 +776,7 @@ augmentConversionForManagedClusterWindowsProfile_STATUS: Interface augmentConversionForManagedCluster_STATUS: Interface augmentConversionForManagedCluster_Spec: Interface augmentConversionForManagedClustersAgentPool: Interface +augmentConversionForManagedClustersAgentPoolOperatorSpec: Interface augmentConversionForManagedClustersAgentPool_STATUS: Interface augmentConversionForManagedClustersAgentPool_Spec: Interface augmentConversionForPowerState_STATUS: Interface diff --git a/v2/api/containerservice/v1api20210501/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20210501/storage/zz_generated.deepcopy.go index 2875a7b1550..38ba0d98b72 100644 --- a/v2/api/containerservice/v1api20210501/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20210501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1989,6 +1990,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -1996,6 +2008,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -3283,6 +3306,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -3606,6 +3673,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20210501/structure.txt b/v2/api/containerservice/v1api20210501/structure.txt index 1d2dd51df7e..4fe6a90ea12 100644 --- a/v2/api/containerservice/v1api20210501/structure.txt +++ b/v2/api/containerservice/v1api20210501/structure.txt @@ -237,7 +237,9 @@ ManagedCluster: Resource │ │ └── ServiceCidr: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^([0-9]{1,3}\\.){3}[0-9]{1,3}(\\/([0-9]|[1-2][0-9]|3[0-2]))?$" │ ├── NodeResourceGroup: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -573,7 +575,7 @@ ManagedCluster: Resource └── "Windows_Server" ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (35 properties) +├── Spec: Object (36 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── Count: *int @@ -646,6 +648,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixIDReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 diff --git a/v2/api/containerservice/v1api20210501/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20210501/zz_generated.deepcopy.go index 94d7f184e43..c85198eac89 100644 --- a/v2/api/containerservice/v1api20210501/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20210501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1707,6 +1708,28 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -2854,6 +2877,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -3170,6 +3230,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20230201/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20230201/managed_cluster_types_gen.go index 9b146a96334..51fbab62baf 100644 --- a/v2/api/containerservice/v1api20230201/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20230201/managed_cluster_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -108,6 +109,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -273,14 +294,14 @@ func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnin if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, - cluster.Spec.OperatorSpec.ConfigMaps.PrincipalId, + var toValidate []*genruntime.ConfigMapDestination + if cluster.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + cluster.Spec.OperatorSpec.ConfigMaps.PrincipalId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -302,14 +323,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -8878,9 +8899,15 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -8888,6 +8915,24 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -8900,6 +8945,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -8921,6 +8984,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -8933,6 +9014,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen.go index 066ccd0d328..6124a8d6e8f 100644 --- a/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -408,6 +453,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: Both patch version (e.g. 1.20.13) and (e.g. 1.20) are supported. // When is specified, the latest supported GA patch version is chosen automatically. Updating the cluster // with the same once it has been created (e.g. 1.14.x -> 1.14) will not trigger an upgrade, even if a newer @@ -972,6 +1021,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1347,6 +1398,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -1649,6 +1712,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -4224,6 +4299,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Ephemeral","Managed"} type OSDiskType string diff --git a/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen_test.go index 6c37d39f5f9..20b1a283fa4 100644 --- a/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20230201/managed_clusters_agent_pool_types_gen_test.go @@ -1033,6 +1033,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230201s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1365,6 +1462,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["CreationData"] = gen.PtrOf(CreationDataGenerator()) gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20230201/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20230201/storage/managed_cluster_types_gen.go index 5d938982f53..18323e08c57 100644 --- a/v2/api/containerservice/v1api20230201/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20230201/storage/managed_cluster_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -80,6 +82,26 @@ func (cluster *ManagedCluster) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -5659,9 +5681,11 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Storage version of v1api20230201.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec @@ -5669,6 +5693,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -5681,6 +5723,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -5718,6 +5778,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -5730,6 +5808,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen.go index e37fb7c2a16..610f94604fe 100644 --- a/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231001/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (pool *ManagedClustersAgentPool) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -275,14 +298,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -509,6 +533,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -788,6 +824,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -2335,6 +2383,136 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Storage version of v1api20230201.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230201.PowerState type PowerState struct { Code *string `json:"code,omitempty"` @@ -2437,6 +2615,11 @@ type augmentConversionForLinuxOSConfig_STATUS interface { AssignPropertiesTo(dst *storage.LinuxOSConfig_STATUS) error } +type augmentConversionForManagedClustersAgentPoolOperatorSpec interface { + AssignPropertiesFrom(src *storage.ManagedClustersAgentPoolOperatorSpec) error + AssignPropertiesTo(dst *storage.ManagedClustersAgentPoolOperatorSpec) error +} + type augmentConversionForPowerState interface { AssignPropertiesFrom(src *storage.PowerState) error AssignPropertiesTo(dst *storage.PowerState) error diff --git a/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen_test.go index 42cdca36f8a..8b2bdbd1ca6 100644 --- a/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20230201/storage/managed_clusters_agent_pool_types_gen_test.go @@ -1033,6 +1033,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231001s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1346,6 +1443,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["CreationData"] = gen.PtrOf(CreationDataGenerator()) gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20230201/storage/structure.txt b/v2/api/containerservice/v1api20230201/storage/structure.txt index 568d864d497..61c3f32a87e 100644 --- a/v2/api/containerservice/v1api20230201/storage/structure.txt +++ b/v2/api/containerservice/v1api20230201/storage/structure.txt @@ -239,12 +239,14 @@ ManagedCluster: Resource │ ├── OidcIssuerProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -709,7 +711,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20230201.ManagedCluster -├── Spec: Object (42 properties) +├── Spec: Object (43 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── Count: *int @@ -779,6 +781,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -1007,6 +1013,7 @@ augmentConversionForManagedClusterWorkloadAutoScalerProfile_STATUS: Interface augmentConversionForManagedCluster_STATUS: Interface augmentConversionForManagedCluster_Spec: Interface augmentConversionForManagedClustersAgentPool: Interface +augmentConversionForManagedClustersAgentPoolOperatorSpec: Interface augmentConversionForManagedClustersAgentPool_STATUS: Interface augmentConversionForManagedClustersAgentPool_Spec: Interface augmentConversionForPowerState: Interface diff --git a/v2/api/containerservice/v1api20230201/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20230201/storage/zz_generated.deepcopy.go index 599ad8e7122..0c3fa3337eb 100644 --- a/v2/api/containerservice/v1api20230201/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20230201/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -2672,6 +2673,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) @@ -2684,6 +2696,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -4779,6 +4802,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -5137,6 +5204,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20230201/structure.txt b/v2/api/containerservice/v1api20230201/structure.txt index 37f63048cc9..ca7ef74c21d 100644 --- a/v2/api/containerservice/v1api20230201/structure.txt +++ b/v2/api/containerservice/v1api20230201/structure.txt @@ -289,10 +289,12 @@ ManagedCluster: Resource │ ├── NodeResourceGroup: *string │ ├── OidcIssuerProfile: *Object (1 property) │ │ └── Enabled: *bool -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -762,7 +764,7 @@ ManagedCluster: Resource └── Enabled: *bool ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (40 properties) +├── Spec: Object (41 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── Count: *int @@ -838,6 +840,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 diff --git a/v2/api/containerservice/v1api20230201/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20230201/zz_generated.deepcopy.go index 272dcc0f8d2..78f123ea32b 100644 --- a/v2/api/containerservice/v1api20230201/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20230201/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230201 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -2271,11 +2272,33 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -4063,6 +4086,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -4414,6 +4474,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20230315preview/fleet_types_gen.go b/v2/api/containerservice/v1api20230315preview/fleet_types_gen.go index 561373fb804..f9e7e34249e 100644 --- a/v2/api/containerservice/v1api20230315preview/fleet_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/fleet_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (fleet *Fleet) defaultAzureName() { // defaultImpl applies the code generated defaults to the Fleet resource func (fleet *Fleet) defaultImpl() { fleet.defaultAzureName() } +var _ configmaps.Exporter = &Fleet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fleet *Fleet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fleet.Spec.OperatorSpec == nil { + return nil + } + return fleet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Fleet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fleet *Fleet) SecretDestinationExpressions() []*core.DestinationExpression { + if fleet.Spec.OperatorSpec == nil { + return nil + } + return fleet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Fleet{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (fleet *Fleet) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (fleet *Fleet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){fleet.validateResourceReferences, fleet.validateOwnerReference, fleet.validateSecretDestinations} + return []func() (admission.Warnings, error){fleet.validateResourceReferences, fleet.validateOwnerReference, fleet.validateSecretDestinations, fleet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (fleet *Fleet) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return fleet.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return fleet.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (fleet *Fleet) validateConfigMapDestinations() (admission.Warnings, error) { + if fleet.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(fleet, nil, fleet.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,13 +286,13 @@ func (fleet *Fleet) validateSecretDestinations() (admission.Warnings, error) { if fleet.Spec.OperatorSpec == nil { return nil, nil } - if fleet.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - fleet.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if fleet.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + fleet.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(fleet, toValidate, fleet.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1168,6 +1201,12 @@ func (profile *FleetHubProfile_STATUS) AssignProperties_To_FleetHubProfile_STATU // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FleetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FleetOperatorSecrets `json:"secrets,omitempty"` } @@ -1175,6 +1214,42 @@ type FleetOperatorSpec struct { // AssignProperties_From_FleetOperatorSpec populates our FleetOperatorSpec from the provided source FleetOperatorSpec func (operator *FleetOperatorSpec) AssignProperties_From_FleetOperatorSpec(source *storage.FleetOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FleetOperatorSecrets @@ -1196,6 +1271,42 @@ func (operator *FleetOperatorSpec) AssignProperties_To_FleetOperatorSpec(destina // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FleetOperatorSecrets diff --git a/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen.go b/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen.go index 91e7b349a84..66b6668a1bd 100644 --- a/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (member *FleetsMember) defaultAzureName() { // defaultImpl applies the code generated defaults to the FleetsMember resource func (member *FleetsMember) defaultImpl() { member.defaultAzureName() } +var _ configmaps.Exporter = &FleetsMember{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (member *FleetsMember) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if member.Spec.OperatorSpec == nil { + return nil + } + return member.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FleetsMember{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (member *FleetsMember) SecretDestinationExpressions() []*core.DestinationExpression { + if member.Spec.OperatorSpec == nil { + return nil + } + return member.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FleetsMember{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (member *FleetsMember) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (member *FleetsMember) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){member.validateResourceReferences, member.validateOwnerReference} + return []func() (admission.Warnings, error){member.validateResourceReferences, member.validateOwnerReference, member.validateSecretDestinations, member.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (member *FleetsMember) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return member.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return member.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return member.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (member *FleetsMember) validateConfigMapDestinations() (admission.Warnings, error) { + if member.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(member, nil, member.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (member *FleetsMember) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (member *FleetsMember) validateSecretDestinations() (admission.Warnings, error) { + if member.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(member, nil, member.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (member *FleetsMember) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FleetsMember) @@ -345,6 +390,10 @@ type FleetsMember_Spec struct { // Group: The group this member belongs to for multi-cluster update management. Group *string `json:"group,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FleetsMemberOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -409,6 +458,8 @@ func (member *FleetsMember_Spec) PopulateFromARM(owner genruntime.ArbitraryOwner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": member.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -491,6 +542,18 @@ func (member *FleetsMember_Spec) AssignProperties_From_FleetsMember_Spec(source member.Group = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FleetsMemberOperatorSpec + err := operatorSpec.AssignProperties_From_FleetsMemberOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FleetsMemberOperatorSpec() to populate field OperatorSpec") + } + member.OperatorSpec = &operatorSpec + } else { + member.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -527,6 +590,18 @@ func (member *FleetsMember_Spec) AssignProperties_To_FleetsMember_Spec(destinati destination.Group = nil } + // OperatorSpec + if member.OperatorSpec != nil { + var operatorSpec storage.FleetsMemberOperatorSpec + err := member.OperatorSpec.AssignProperties_To_FleetsMemberOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FleetsMemberOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = member.OriginalVersion() @@ -876,6 +951,110 @@ var fleetMemberProvisioningState_STATUS_Values = map[string]FleetMemberProvision "updating": FleetMemberProvisioningState_STATUS_Updating, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FleetsMemberOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FleetsMemberOperatorSpec populates our FleetsMemberOperatorSpec from the provided source FleetsMemberOperatorSpec +func (operator *FleetsMemberOperatorSpec) AssignProperties_From_FleetsMemberOperatorSpec(source *storage.FleetsMemberOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FleetsMemberOperatorSpec populates the provided destination FleetsMemberOperatorSpec from our FleetsMemberOperatorSpec +func (operator *FleetsMemberOperatorSpec) AssignProperties_To_FleetsMemberOperatorSpec(destination *storage.FleetsMemberOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FleetsMember{}, &FleetsMemberList{}) } diff --git a/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen_test.go b/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen_test.go index fe846d428cb..5e8ab7a2a50 100644 --- a/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen_test.go +++ b/v2/api/containerservice/v1api20230315preview/fleets_member_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForFleetsMember(gens map[string]gopter.Gen) { gens["Status"] = FleetsMember_STATUSGenerator() } +func Test_FleetsMemberOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FleetsMemberOperatorSpec to FleetsMemberOperatorSpec via AssignProperties_To_FleetsMemberOperatorSpec & AssignProperties_From_FleetsMemberOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFleetsMemberOperatorSpec, FleetsMemberOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFleetsMemberOperatorSpec tests if a specific instance of FleetsMemberOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFleetsMemberOperatorSpec(subject FleetsMemberOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FleetsMemberOperatorSpec + err := copied.AssignProperties_To_FleetsMemberOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FleetsMemberOperatorSpec + err = actual.AssignProperties_From_FleetsMemberOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FleetsMemberOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FleetsMemberOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFleetsMemberOperatorSpec, FleetsMemberOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFleetsMemberOperatorSpec runs a test to see if a specific instance of FleetsMemberOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFleetsMemberOperatorSpec(subject FleetsMemberOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FleetsMemberOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FleetsMemberOperatorSpec instances for property testing - lazily instantiated by +// FleetsMemberOperatorSpecGenerator() +var fleetsMemberOperatorSpecGenerator gopter.Gen + +// FleetsMemberOperatorSpecGenerator returns a generator of FleetsMemberOperatorSpec instances for property testing. +func FleetsMemberOperatorSpecGenerator() gopter.Gen { + if fleetsMemberOperatorSpecGenerator != nil { + return fleetsMemberOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fleetsMemberOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FleetsMemberOperatorSpec{}), generators) + + return fleetsMemberOperatorSpecGenerator +} + func Test_FleetsMember_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -378,6 +475,9 @@ func RunJSONSerializationTestForFleetsMember_Spec(subject FleetsMember_Spec) str var fleetsMember_SpecGenerator gopter.Gen // FleetsMember_SpecGenerator returns a generator of FleetsMember_Spec instances for property testing. +// We first initialize fleetsMember_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FleetsMember_SpecGenerator() gopter.Gen { if fleetsMember_SpecGenerator != nil { return fleetsMember_SpecGenerator @@ -387,6 +487,12 @@ func FleetsMember_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFleetsMember_Spec(generators) fleetsMember_SpecGenerator = gen.Struct(reflect.TypeOf(FleetsMember_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFleetsMember_Spec(generators) + AddRelatedPropertyGeneratorsForFleetsMember_Spec(generators) + fleetsMember_SpecGenerator = gen.Struct(reflect.TypeOf(FleetsMember_Spec{}), generators) + return fleetsMember_SpecGenerator } @@ -395,3 +501,8 @@ func AddIndependentPropertyGeneratorsForFleetsMember_Spec(gens map[string]gopter gens["AzureName"] = gen.AlphaString() gens["Group"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFleetsMember_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFleetsMember_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FleetsMemberOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen.go b/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen.go index 4e90a75b49e..2682693c0df 100644 --- a/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (updateRun *FleetsUpdateRun) defaultAzureName() { // defaultImpl applies the code generated defaults to the FleetsUpdateRun resource func (updateRun *FleetsUpdateRun) defaultImpl() { updateRun.defaultAzureName() } +var _ configmaps.Exporter = &FleetsUpdateRun{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (updateRun *FleetsUpdateRun) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if updateRun.Spec.OperatorSpec == nil { + return nil + } + return updateRun.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FleetsUpdateRun{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (updateRun *FleetsUpdateRun) SecretDestinationExpressions() []*core.DestinationExpression { + if updateRun.Spec.OperatorSpec == nil { + return nil + } + return updateRun.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FleetsUpdateRun{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (updateRun *FleetsUpdateRun) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (updateRun *FleetsUpdateRun) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){updateRun.validateResourceReferences, updateRun.validateOwnerReference} + return []func() (admission.Warnings, error){updateRun.validateResourceReferences, updateRun.validateOwnerReference, updateRun.validateSecretDestinations, updateRun.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (updateRun *FleetsUpdateRun) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return updateRun.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return updateRun.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return updateRun.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (updateRun *FleetsUpdateRun) validateConfigMapDestinations() (admission.Warnings, error) { + if updateRun.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(updateRun, nil, updateRun.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (updateRun *FleetsUpdateRun) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (updateRun *FleetsUpdateRun) validateSecretDestinations() (admission.Warnings, error) { + if updateRun.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(updateRun, nil, updateRun.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (updateRun *FleetsUpdateRun) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FleetsUpdateRun) @@ -339,6 +384,10 @@ type FleetsUpdateRun_Spec struct { // modified until the run is started. ManagedClusterUpdate *ManagedClusterUpdate `json:"managedClusterUpdate,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FleetsUpdateRunOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -416,6 +465,8 @@ func (updateRun *FleetsUpdateRun_Spec) PopulateFromARM(owner genruntime.Arbitrar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": updateRun.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -508,6 +559,18 @@ func (updateRun *FleetsUpdateRun_Spec) AssignProperties_From_FleetsUpdateRun_Spe updateRun.ManagedClusterUpdate = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FleetsUpdateRunOperatorSpec + err := operatorSpec.AssignProperties_From_FleetsUpdateRunOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FleetsUpdateRunOperatorSpec() to populate field OperatorSpec") + } + updateRun.OperatorSpec = &operatorSpec + } else { + updateRun.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -552,6 +615,18 @@ func (updateRun *FleetsUpdateRun_Spec) AssignProperties_To_FleetsUpdateRun_Spec( destination.ManagedClusterUpdate = nil } + // OperatorSpec + if updateRun.OperatorSpec != nil { + var operatorSpec storage.FleetsUpdateRunOperatorSpec + err := updateRun.OperatorSpec.AssignProperties_To_FleetsUpdateRunOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FleetsUpdateRunOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = updateRun.OriginalVersion() @@ -991,6 +1066,110 @@ func (updateRun *FleetsUpdateRun_STATUS) AssignProperties_To_FleetsUpdateRun_STA return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FleetsUpdateRunOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FleetsUpdateRunOperatorSpec populates our FleetsUpdateRunOperatorSpec from the provided source FleetsUpdateRunOperatorSpec +func (operator *FleetsUpdateRunOperatorSpec) AssignProperties_From_FleetsUpdateRunOperatorSpec(source *storage.FleetsUpdateRunOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FleetsUpdateRunOperatorSpec populates the provided destination FleetsUpdateRunOperatorSpec from our FleetsUpdateRunOperatorSpec +func (operator *FleetsUpdateRunOperatorSpec) AssignProperties_To_FleetsUpdateRunOperatorSpec(destination *storage.FleetsUpdateRunOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The update to be applied to the ManagedClusters. type ManagedClusterUpdate struct { // +kubebuilder:validation:Required diff --git a/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen_test.go b/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen_test.go index 1f245f3d6e0..91e6b079599 100644 --- a/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen_test.go +++ b/v2/api/containerservice/v1api20230315preview/fleets_update_run_types_gen_test.go @@ -505,6 +505,103 @@ func AddRelatedPropertyGeneratorsForFleetsUpdateRun(gens map[string]gopter.Gen) gens["Status"] = FleetsUpdateRun_STATUSGenerator() } +func Test_FleetsUpdateRunOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FleetsUpdateRunOperatorSpec to FleetsUpdateRunOperatorSpec via AssignProperties_To_FleetsUpdateRunOperatorSpec & AssignProperties_From_FleetsUpdateRunOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFleetsUpdateRunOperatorSpec, FleetsUpdateRunOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFleetsUpdateRunOperatorSpec tests if a specific instance of FleetsUpdateRunOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFleetsUpdateRunOperatorSpec(subject FleetsUpdateRunOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FleetsUpdateRunOperatorSpec + err := copied.AssignProperties_To_FleetsUpdateRunOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FleetsUpdateRunOperatorSpec + err = actual.AssignProperties_From_FleetsUpdateRunOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FleetsUpdateRunOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FleetsUpdateRunOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFleetsUpdateRunOperatorSpec, FleetsUpdateRunOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFleetsUpdateRunOperatorSpec runs a test to see if a specific instance of FleetsUpdateRunOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFleetsUpdateRunOperatorSpec(subject FleetsUpdateRunOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FleetsUpdateRunOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FleetsUpdateRunOperatorSpec instances for property testing - lazily instantiated by +// FleetsUpdateRunOperatorSpecGenerator() +var fleetsUpdateRunOperatorSpecGenerator gopter.Gen + +// FleetsUpdateRunOperatorSpecGenerator returns a generator of FleetsUpdateRunOperatorSpec instances for property testing. +func FleetsUpdateRunOperatorSpecGenerator() gopter.Gen { + if fleetsUpdateRunOperatorSpecGenerator != nil { + return fleetsUpdateRunOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fleetsUpdateRunOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FleetsUpdateRunOperatorSpec{}), generators) + + return fleetsUpdateRunOperatorSpecGenerator +} + func Test_FleetsUpdateRun_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -744,6 +841,7 @@ func AddIndependentPropertyGeneratorsForFleetsUpdateRun_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForFleetsUpdateRun_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForFleetsUpdateRun_Spec(gens map[string]gopter.Gen) { gens["ManagedClusterUpdate"] = gen.PtrOf(ManagedClusterUpdateGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FleetsUpdateRunOperatorSpecGenerator()) gens["Strategy"] = gen.PtrOf(UpdateRunStrategyGenerator()) } diff --git a/v2/api/containerservice/v1api20230315preview/storage/fleet_types_gen.go b/v2/api/containerservice/v1api20230315preview/storage/fleet_types_gen.go index 40d83107977..62118f2ec6d 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/fleet_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/storage/fleet_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20230201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (fleet *Fleet) SetConditions(conditions conditions.Conditions) { fleet.Status.Conditions = conditions } +var _ configmaps.Exporter = &Fleet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (fleet *Fleet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if fleet.Spec.OperatorSpec == nil { + return nil + } + return fleet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Fleet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (fleet *Fleet) SecretDestinationExpressions() []*core.DestinationExpression { + if fleet.Spec.OperatorSpec == nil { + return nil + } + return fleet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Fleet{} // AzureName returns the Azure name of the resource @@ -239,8 +262,10 @@ type FleetHubProfile_STATUS struct { // Storage version of v1api20230315preview.FleetOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FleetOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FleetOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FleetOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20230315preview.SystemData_STATUS diff --git a/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen.go b/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen.go index 8b75843c1fe..526b9a13cc3 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (member *FleetsMember) SetConditions(conditions conditions.Conditions) { member.Status.Conditions = conditions } +var _ configmaps.Exporter = &FleetsMember{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (member *FleetsMember) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if member.Spec.OperatorSpec == nil { + return nil + } + return member.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FleetsMember{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (member *FleetsMember) SecretDestinationExpressions() []*core.DestinationExpression { + if member.Spec.OperatorSpec == nil { + return nil + } + return member.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FleetsMember{} // AzureName returns the Azure name of the resource @@ -150,6 +173,7 @@ type FleetsMember_Spec struct { // '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ContainerService/managedClusters/{clusterName}'. ClusterResourceReference *genruntime.ResourceReference `armReference:"ClusterResourceId" json:"clusterResourceReference,omitempty"` Group *string `json:"group,omitempty"` + OperatorSpec *FleetsMemberOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -214,6 +238,14 @@ func (member *FleetsMember_STATUS) ConvertStatusTo(destination genruntime.Conver return destination.ConvertStatusFrom(member) } +// Storage version of v1api20230315preview.FleetsMemberOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FleetsMemberOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FleetsMember{}, &FleetsMemberList{}) } diff --git a/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen_test.go b/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen_test.go index 2adbf11e96a..cb695167936 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen_test.go +++ b/v2/api/containerservice/v1api20230315preview/storage/fleets_member_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForFleetsMember(gens map[string]gopter.Gen) { gens["Status"] = FleetsMember_STATUSGenerator() } +func Test_FleetsMemberOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FleetsMemberOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFleetsMemberOperatorSpec, FleetsMemberOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFleetsMemberOperatorSpec runs a test to see if a specific instance of FleetsMemberOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFleetsMemberOperatorSpec(subject FleetsMemberOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FleetsMemberOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FleetsMemberOperatorSpec instances for property testing - lazily instantiated by +// FleetsMemberOperatorSpecGenerator() +var fleetsMemberOperatorSpecGenerator gopter.Gen + +// FleetsMemberOperatorSpecGenerator returns a generator of FleetsMemberOperatorSpec instances for property testing. +func FleetsMemberOperatorSpecGenerator() gopter.Gen { + if fleetsMemberOperatorSpecGenerator != nil { + return fleetsMemberOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fleetsMemberOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FleetsMemberOperatorSpec{}), generators) + + return fleetsMemberOperatorSpecGenerator +} + func Test_FleetsMember_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForFleetsMember_Spec(subject FleetsMember_Spec) str var fleetsMember_SpecGenerator gopter.Gen // FleetsMember_SpecGenerator returns a generator of FleetsMember_Spec instances for property testing. +// We first initialize fleetsMember_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FleetsMember_SpecGenerator() gopter.Gen { if fleetsMember_SpecGenerator != nil { return fleetsMember_SpecGenerator @@ -211,6 +269,12 @@ func FleetsMember_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFleetsMember_Spec(generators) fleetsMember_SpecGenerator = gen.Struct(reflect.TypeOf(FleetsMember_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFleetsMember_Spec(generators) + AddRelatedPropertyGeneratorsForFleetsMember_Spec(generators) + fleetsMember_SpecGenerator = gen.Struct(reflect.TypeOf(FleetsMember_Spec{}), generators) + return fleetsMember_SpecGenerator } @@ -220,3 +284,8 @@ func AddIndependentPropertyGeneratorsForFleetsMember_Spec(gens map[string]gopter gens["Group"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFleetsMember_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFleetsMember_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FleetsMemberOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen.go b/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen.go index 47c877e9e01..a0cb5afc6ad 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen.go +++ b/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (updateRun *FleetsUpdateRun) SetConditions(conditions conditions.Conditions updateRun.Status.Conditions = conditions } +var _ configmaps.Exporter = &FleetsUpdateRun{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (updateRun *FleetsUpdateRun) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if updateRun.Spec.OperatorSpec == nil { + return nil + } + return updateRun.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FleetsUpdateRun{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (updateRun *FleetsUpdateRun) SecretDestinationExpressions() []*core.DestinationExpression { + if updateRun.Spec.OperatorSpec == nil { + return nil + } + return updateRun.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FleetsUpdateRun{} // AzureName returns the Azure name of the resource @@ -143,9 +166,10 @@ type FleetsUpdateRunList struct { type FleetsUpdateRun_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ManagedClusterUpdate *ManagedClusterUpdate `json:"managedClusterUpdate,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ManagedClusterUpdate *ManagedClusterUpdate `json:"managedClusterUpdate,omitempty"` + OperatorSpec *FleetsUpdateRunOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -211,6 +235,14 @@ func (updateRun *FleetsUpdateRun_STATUS) ConvertStatusTo(destination genruntime. return destination.ConvertStatusFrom(updateRun) } +// Storage version of v1api20230315preview.FleetsUpdateRunOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FleetsUpdateRunOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230315preview.ManagedClusterUpdate // The update to be applied to the ManagedClusters. type ManagedClusterUpdate struct { diff --git a/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen_test.go b/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen_test.go index 4d059382671..0713e63b766 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen_test.go +++ b/v2/api/containerservice/v1api20230315preview/storage/fleets_update_run_types_gen_test.go @@ -293,6 +293,61 @@ func AddRelatedPropertyGeneratorsForFleetsUpdateRun(gens map[string]gopter.Gen) gens["Status"] = FleetsUpdateRun_STATUSGenerator() } +func Test_FleetsUpdateRunOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FleetsUpdateRunOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFleetsUpdateRunOperatorSpec, FleetsUpdateRunOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFleetsUpdateRunOperatorSpec runs a test to see if a specific instance of FleetsUpdateRunOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFleetsUpdateRunOperatorSpec(subject FleetsUpdateRunOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FleetsUpdateRunOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FleetsUpdateRunOperatorSpec instances for property testing - lazily instantiated by +// FleetsUpdateRunOperatorSpecGenerator() +var fleetsUpdateRunOperatorSpecGenerator gopter.Gen + +// FleetsUpdateRunOperatorSpecGenerator returns a generator of FleetsUpdateRunOperatorSpec instances for property testing. +func FleetsUpdateRunOperatorSpecGenerator() gopter.Gen { + if fleetsUpdateRunOperatorSpecGenerator != nil { + return fleetsUpdateRunOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fleetsUpdateRunOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FleetsUpdateRunOperatorSpec{}), generators) + + return fleetsUpdateRunOperatorSpecGenerator +} + func Test_FleetsUpdateRun_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -449,6 +504,7 @@ func AddIndependentPropertyGeneratorsForFleetsUpdateRun_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForFleetsUpdateRun_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForFleetsUpdateRun_Spec(gens map[string]gopter.Gen) { gens["ManagedClusterUpdate"] = gen.PtrOf(ManagedClusterUpdateGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FleetsUpdateRunOperatorSpecGenerator()) gens["Strategy"] = gen.PtrOf(UpdateRunStrategyGenerator()) } diff --git a/v2/api/containerservice/v1api20230315preview/storage/structure.txt b/v2/api/containerservice/v1api20230315preview/storage/structure.txt index 3056f2573a8..14b37dfa51b 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/structure.txt +++ b/v2/api/containerservice/v1api20230315preview/storage/structure.txt @@ -11,8 +11,10 @@ Fleet: Resource │ │ ├── DnsPrefix: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── UserCredentials: *genruntime.SecretDestination @@ -45,10 +47,14 @@ Fleet: Resource └── Type: *string FleetsMember: Resource ├── Owner: containerservice/v1api20230315preview.Fleet -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── ClusterResourceReference: *genruntime.ResourceReference │ ├── Group: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -72,7 +78,7 @@ FleetsMember: Resource └── Type: *string FleetsUpdateRun: Resource ├── Owner: containerservice/v1api20230315preview.Fleet -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── ManagedClusterUpdate: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -80,6 +86,10 @@ FleetsUpdateRun: Resource │ │ ├── KubernetesVersion: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Type: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/containerservice/v1api20230315preview/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20230315preview/storage/zz_generated.deepcopy.go index e16d307dc9e..33164c3a7cf 100644 --- a/v2/api/containerservice/v1api20230315preview/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20230315preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -298,6 +299,17 @@ func (in *FleetOperatorSecrets) DeepCopy() *FleetOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetOperatorSpec) DeepCopyInto(out *FleetOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -305,6 +317,17 @@ func (in *FleetOperatorSpec) DeepCopyInto(out *FleetOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FleetOperatorSecrets) @@ -506,6 +529,50 @@ func (in *FleetsMemberList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FleetsMemberOperatorSpec) DeepCopyInto(out *FleetsMemberOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FleetsMemberOperatorSpec. +func (in *FleetsMemberOperatorSpec) DeepCopy() *FleetsMemberOperatorSpec { + if in == nil { + return nil + } + out := new(FleetsMemberOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetsMember_STATUS) DeepCopyInto(out *FleetsMember_STATUS) { *out = *in @@ -588,6 +655,11 @@ func (in *FleetsMember_Spec) DeepCopyInto(out *FleetsMember_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FleetsMemberOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -671,6 +743,50 @@ func (in *FleetsUpdateRunList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FleetsUpdateRunOperatorSpec) DeepCopyInto(out *FleetsUpdateRunOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FleetsUpdateRunOperatorSpec. +func (in *FleetsUpdateRunOperatorSpec) DeepCopy() *FleetsUpdateRunOperatorSpec { + if in == nil { + return nil + } + out := new(FleetsUpdateRunOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetsUpdateRun_STATUS) DeepCopyInto(out *FleetsUpdateRun_STATUS) { *out = *in @@ -753,6 +869,11 @@ func (in *FleetsUpdateRun_Spec) DeepCopyInto(out *FleetsUpdateRun_Spec) { *out = new(ManagedClusterUpdate) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FleetsUpdateRunOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20230315preview/structure.txt b/v2/api/containerservice/v1api20230315preview/structure.txt index 8e9170a5fca..eb6d5177512 100644 --- a/v2/api/containerservice/v1api20230315preview/structure.txt +++ b/v2/api/containerservice/v1api20230315preview/structure.txt @@ -16,7 +16,9 @@ Fleet: Resource │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-]{0,52}[a-zA-Z0-9]$" │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── UserCredentials: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -57,7 +59,7 @@ Fleet: Resource └── Type: *string FleetsMember: Resource ├── Owner: Fleet -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ ├── Rule 1: MinLength: 1 @@ -67,6 +69,9 @@ FleetsMember: Resource │ │ ├── Rule 0: MaxLength: 50 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (9 properties) ├── ClusterResourceId: *string @@ -100,7 +105,7 @@ FleetsMember: Resource └── Type: *string FleetsUpdateRun: Resource ├── Owner: Fleet -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ ├── Rule 1: MinLength: 1 @@ -111,6 +116,9 @@ FleetsUpdateRun: Resource │ │ └── Type: *Enum (2 values) │ │ ├── "Full" │ │ └── "NodeImageOnly" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Strategy: *Object (1 property) │ └── Stages: Object (3 properties)[] diff --git a/v2/api/containerservice/v1api20230315preview/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20230315preview/zz_generated.deepcopy.go index d2f797c9ca8..70a8e9682f0 100644 --- a/v2/api/containerservice/v1api20230315preview/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20230315preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230315preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -256,6 +257,28 @@ func (in *FleetOperatorSecrets) DeepCopy() *FleetOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetOperatorSpec) DeepCopyInto(out *FleetOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FleetOperatorSecrets) @@ -443,6 +466,43 @@ func (in *FleetsMemberList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FleetsMemberOperatorSpec) DeepCopyInto(out *FleetsMemberOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FleetsMemberOperatorSpec. +func (in *FleetsMemberOperatorSpec) DeepCopy() *FleetsMemberOperatorSpec { + if in == nil { + return nil + } + out := new(FleetsMemberOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetsMember_STATUS) DeepCopyInto(out *FleetsMember_STATUS) { *out = *in @@ -518,6 +578,11 @@ func (in *FleetsMember_Spec) DeepCopyInto(out *FleetsMember_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FleetsMemberOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -594,6 +659,43 @@ func (in *FleetsUpdateRunList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FleetsUpdateRunOperatorSpec) DeepCopyInto(out *FleetsUpdateRunOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FleetsUpdateRunOperatorSpec. +func (in *FleetsUpdateRunOperatorSpec) DeepCopy() *FleetsUpdateRunOperatorSpec { + if in == nil { + return nil + } + out := new(FleetsUpdateRunOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FleetsUpdateRun_STATUS) DeepCopyInto(out *FleetsUpdateRun_STATUS) { *out = *in @@ -669,6 +771,11 @@ func (in *FleetsUpdateRun_Spec) DeepCopyInto(out *FleetsUpdateRun_Spec) { *out = new(ManagedClusterUpdate) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FleetsUpdateRunOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20231001/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20231001/managed_cluster_types_gen.go index 7cd01b2aa6b..db91f6d4699 100644 --- a/v2/api/containerservice/v1api20231001/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20231001/managed_cluster_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -276,14 +297,14 @@ func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnin if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, - cluster.Spec.OperatorSpec.ConfigMaps.PrincipalId, + var toValidate []*genruntime.ConfigMapDestination + if cluster.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + cluster.Spec.OperatorSpec.ConfigMaps.PrincipalId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -305,14 +326,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -10260,9 +10281,15 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -10270,6 +10297,24 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -10282,6 +10327,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -10303,6 +10366,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -10315,6 +10396,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen.go index 7fa38173dda..51e56b94fca 100644 --- a/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -417,6 +462,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: Both patch version (e.g. 1.20.13) and (e.g. 1.20) are supported. // When is specified, the latest supported GA patch version is chosen automatically. Updating the cluster // with the same once it has been created (e.g. 1.14.x -> 1.14) will not trigger an upgrade, even if a newer @@ -1015,6 +1064,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1410,6 +1461,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -1732,6 +1795,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -4887,6 +4962,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The default is 'Ephemeral' if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, // defaults to 'Managed'. May not be changed after creation. For more information see [Ephemeral // OS](https://docs.microsoft.com/azure/aks/cluster-configuration#ephemeral-os). diff --git a/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen_test.go index ee059542a8f..7d2c8663bf8 100644 --- a/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20231001/managed_clusters_agent_pool_types_gen_test.go @@ -1463,6 +1463,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231001s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1800,6 +1897,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20231001/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20231001/storage/managed_cluster_types_gen.go index a3d5d9cece0..a4c200a1cdf 100644 --- a/v2/api/containerservice/v1api20231001/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20231001/storage/managed_cluster_types_gen.go @@ -12,6 +12,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -71,6 +73,26 @@ func (cluster *ManagedCluster) ConvertTo(hub conversion.Hub) error { return cluster.AssignProperties_To_ManagedCluster(destination) } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -6123,9 +6145,11 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Storage version of v1api20231001.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec @@ -6133,6 +6157,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -6145,6 +6187,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -6182,6 +6242,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -6194,6 +6272,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen.go index d6a3c058291..d4956ba0b33 100644 --- a/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen.go @@ -9,6 +9,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20240901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -66,6 +69,26 @@ func (pool *ManagedClustersAgentPool) ConvertTo(hub conversion.Hub) error { return pool.AssignProperties_To_ManagedClustersAgentPool(destination) } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -267,14 +290,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -507,6 +531,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -799,6 +835,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -2757,6 +2805,136 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Storage version of v1api20231001.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20231001.PowerState // Describes the Power State of the cluster type PowerState struct { @@ -2870,6 +3048,11 @@ type augmentConversionForLinuxOSConfig_STATUS interface { AssignPropertiesTo(dst *storage.LinuxOSConfig_STATUS) error } +type augmentConversionForManagedClustersAgentPoolOperatorSpec interface { + AssignPropertiesFrom(src *storage.ManagedClustersAgentPoolOperatorSpec) error + AssignPropertiesTo(dst *storage.ManagedClustersAgentPoolOperatorSpec) error +} + type augmentConversionForPowerState interface { AssignPropertiesFrom(src *storage.PowerState) error AssignPropertiesTo(dst *storage.PowerState) error diff --git a/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen_test.go index 37f0bc23e40..99e81c3326a 100644 --- a/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20231001/storage/managed_clusters_agent_pool_types_gen_test.go @@ -1462,6 +1462,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1778,6 +1875,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) } diff --git a/v2/api/containerservice/v1api20231001/storage/structure.txt b/v2/api/containerservice/v1api20231001/storage/structure.txt index 12578b78b51..383c54d8ed2 100644 --- a/v2/api/containerservice/v1api20231001/storage/structure.txt +++ b/v2/api/containerservice/v1api20231001/storage/structure.txt @@ -260,12 +260,14 @@ ManagedCluster: Resource │ ├── OidcIssuerProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -822,7 +824,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20231001.ManagedCluster -├── Spec: Object (44 properties) +├── Spec: Object (45 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── CapacityReservationGroupReference: *genruntime.ResourceReference @@ -905,6 +907,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -1046,8 +1052,12 @@ ManagedClustersAgentPool: Resource └── WorkloadRuntime: *string TrustedAccessRoleBinding: Resource ├── Owner: containerservice/v1api20231001.ManagedCluster -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1196,6 +1206,7 @@ augmentConversionForManagedClusterWorkloadAutoScalerProfile_STATUS: Interface augmentConversionForManagedCluster_STATUS: Interface augmentConversionForManagedCluster_Spec: Interface augmentConversionForManagedClustersAgentPool: Interface +augmentConversionForManagedClustersAgentPoolOperatorSpec: Interface augmentConversionForManagedClustersAgentPool_STATUS: Interface augmentConversionForManagedClustersAgentPool_Spec: Interface augmentConversionForPortRange: Interface @@ -1212,6 +1223,7 @@ augmentConversionForSysctlConfig: Interface augmentConversionForSysctlConfig_STATUS: Interface augmentConversionForSystemData_STATUS: Interface augmentConversionForTrustedAccessRoleBinding: Interface +augmentConversionForTrustedAccessRoleBindingOperatorSpec: Interface augmentConversionForTrustedAccessRoleBinding_STATUS: Interface augmentConversionForTrustedAccessRoleBinding_Spec: Interface augmentConversionForUpgradeOverrideSettings: Interface diff --git a/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen.go index 3174b9f109e..882965b4f08 100644 --- a/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20240901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (binding *TrustedAccessRoleBinding) ConvertTo(hub conversion.Hub) error { return binding.AssignProperties_To_TrustedAccessRoleBinding(destination) } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrustedAccessRoleBinding{} // AzureName returns the Azure name of the resource @@ -235,8 +258,9 @@ type augmentConversionForTrustedAccessRoleBinding interface { type TrustedAccessRoleBinding_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -309,6 +333,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_From_TrustedAcces // AzureName binding.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrustedAccessRoleBindingOperatorSpec + err := operatorSpec.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + binding.OperatorSpec = &operatorSpec + } else { + binding.OperatorSpec = nil + } + // OriginalVersion binding.OriginalVersion = source.OriginalVersion @@ -359,6 +395,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_To_TrustedAccessR // AzureName destination.AzureName = binding.AzureName + // OperatorSpec + if binding.OperatorSpec != nil { + var operatorSpec storage.TrustedAccessRoleBindingOperatorSpec + err := binding.OperatorSpec.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = binding.OriginalVersion @@ -590,6 +638,141 @@ type augmentConversionForTrustedAccessRoleBinding_STATUS interface { AssignPropertiesTo(dst *storage.TrustedAccessRoleBinding_STATUS) error } +// Storage version of v1api20231001.TrustedAccessRoleBindingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrustedAccessRoleBindingOperatorSpec populates our TrustedAccessRoleBindingOperatorSpec from the provided source TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source *storage.TrustedAccessRoleBindingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForTrustedAccessRoleBindingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForTrustedAccessRoleBindingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_TrustedAccessRoleBindingOperatorSpec populates the provided destination TrustedAccessRoleBindingOperatorSpec from our TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(destination *storage.TrustedAccessRoleBindingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForTrustedAccessRoleBindingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForTrustedAccessRoleBindingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForTrustedAccessRoleBindingOperatorSpec interface { + AssignPropertiesFrom(src *storage.TrustedAccessRoleBindingOperatorSpec) error + AssignPropertiesTo(dst *storage.TrustedAccessRoleBindingOperatorSpec) error +} + func init() { SchemeBuilder.Register(&TrustedAccessRoleBinding{}, &TrustedAccessRoleBindingList{}) } diff --git a/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen_test.go index 4a18aa9e73d..6139881bf7e 100644 --- a/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20231001/storage/trusted_access_role_binding_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrustedAccessRoleBindingOperatorSpec to TrustedAccessRoleBindingOperatorSpec via AssignProperties_To_TrustedAccessRoleBindingOperatorSpec & AssignProperties_From_TrustedAccessRoleBindingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec tests if a specific instance of TrustedAccessRoleBindingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.TrustedAccessRoleBindingOperatorSpec + err := copied.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrustedAccessRoleBindingOperatorSpec + err = actual.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -382,6 +482,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["OriginalVersion"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20231001/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20231001/storage/zz_generated.deepcopy.go index d8910091822..976653c56d1 100644 --- a/v2/api/containerservice/v1api20231001/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20231001/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -3436,6 +3437,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) @@ -3448,6 +3460,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -5642,6 +5665,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -6020,6 +6087,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -6916,6 +6988,50 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -6983,6 +7099,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20231001/structure.txt b/v2/api/containerservice/v1api20231001/structure.txt index f0b689a3889..623ccdc0897 100644 --- a/v2/api/containerservice/v1api20231001/structure.txt +++ b/v2/api/containerservice/v1api20231001/structure.txt @@ -326,10 +326,12 @@ ManagedCluster: Resource │ ├── NodeResourceGroup: *string │ ├── OidcIssuerProfile: *Object (1 property) │ │ └── Enabled: *bool -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -890,7 +892,7 @@ ManagedCluster: Resource └── Enabled: *bool ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (42 properties) +├── Spec: Object (43 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 12 @@ -991,6 +993,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 @@ -1175,11 +1180,14 @@ ManagedClustersAgentPool: Resource └── "WasmWasi" TrustedAccessRoleBinding: Resource ├── Owner: ManagedCluster -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 24 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^([A-Za-z0-9-])+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Roles: string[] │ └── SourceResourceReference: *genruntime.ResourceReference diff --git a/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen.go index 583db7fb20e..dc3dacd2050 100644 --- a/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (binding *TrustedAccessRoleBinding) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrustedAccessRoleBinding resource func (binding *TrustedAccessRoleBinding) defaultImpl() { binding.defaultAzureName() } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrustedAccessRoleBinding{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (binding *TrustedAccessRoleBinding) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (binding *TrustedAccessRoleBinding) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference} + return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference, binding.validateSecretDestinations, binding.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (binding *TrustedAccessRoleBinding) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return binding.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (binding *TrustedAccessRoleBinding) validateConfigMapDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (binding *TrustedAccessRoleBinding) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (binding *TrustedAccessRoleBinding) validateSecretDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (binding *TrustedAccessRoleBinding) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrustedAccessRoleBinding) @@ -336,6 +381,10 @@ type TrustedAccessRoleBinding_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -397,6 +446,8 @@ func (binding *TrustedAccessRoleBinding_Spec) PopulateFromARM(owner genruntime.A // Set property "AzureName": binding.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": binding.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -473,6 +524,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_From_TrustedAcces // AzureName binding.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrustedAccessRoleBindingOperatorSpec + err := operatorSpec.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + binding.OperatorSpec = &operatorSpec + } else { + binding.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_To_TrustedAccessR // AzureName destination.AzureName = binding.AzureName + // OperatorSpec + if binding.OperatorSpec != nil { + var operatorSpec storage.TrustedAccessRoleBindingOperatorSpec + err := binding.OperatorSpec.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = binding.OriginalVersion() @@ -802,6 +877,110 @@ func (binding *TrustedAccessRoleBinding_STATUS) AssignProperties_To_TrustedAcces return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrustedAccessRoleBindingOperatorSpec populates our TrustedAccessRoleBindingOperatorSpec from the provided source TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source *storage.TrustedAccessRoleBindingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrustedAccessRoleBindingOperatorSpec populates the provided destination TrustedAccessRoleBindingOperatorSpec from our TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(destination *storage.TrustedAccessRoleBindingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type TrustedAccessRoleBindingProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen_test.go index e6bf8605f0e..a1288674abc 100644 --- a/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20231001/trusted_access_role_binding_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrustedAccessRoleBindingOperatorSpec to TrustedAccessRoleBindingOperatorSpec via AssignProperties_To_TrustedAccessRoleBindingOperatorSpec & AssignProperties_From_TrustedAccessRoleBindingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec tests if a specific instance of TrustedAccessRoleBindingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231001s.TrustedAccessRoleBindingOperatorSpec + err := copied.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrustedAccessRoleBindingOperatorSpec + err = actual.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -379,6 +476,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -388,6 +488,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -396,3 +502,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["AzureName"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20231001/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20231001/zz_generated.deepcopy.go index 82955c5a931..6d25fa5c1e2 100644 --- a/v2/api/containerservice/v1api20231001/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20231001/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20231001 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -2895,11 +2896,33 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -4772,6 +4795,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -5143,6 +5203,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -5941,6 +6006,43 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -6001,6 +6103,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20231102preview/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20231102preview/managed_cluster_types_gen.go index f8f2c1c5ae1..f48ada5f56c 100644 --- a/v2/api/containerservice/v1api20231102preview/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20231102preview/managed_cluster_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -108,6 +109,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -266,13 +287,13 @@ func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnin if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + var toValidate []*genruntime.ConfigMapDestination + if cluster.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -294,14 +315,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -12177,9 +12198,15 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -12187,6 +12214,24 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -12199,6 +12244,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -12220,6 +12283,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -12232,6 +12313,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen.go index bbcf6f140a8..090e4e25ae6 100644 --- a/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -440,6 +485,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: Both patch version and are supported. When is // specified, the latest supported patch version is chosen automatically. Updating the agent pool with the same // once it has been created will not trigger an upgrade, even if a newer patch version is available. As a @@ -1169,6 +1218,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1657,6 +1708,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -2071,6 +2134,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -6100,6 +6175,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Ephemeral","Managed"} type OSDiskType string diff --git a/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen_test.go index 60fd1212272..78ccd8ff4be 100644 --- a/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20231102preview/managed_clusters_agent_pool_types_gen_test.go @@ -2094,6 +2094,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231102ps.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2314,6 +2411,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20231102preview/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20231102preview/storage/managed_cluster_types_gen.go index 1afcbe672a5..a05516f565a 100644 --- a/v2/api/containerservice/v1api20231102preview/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20231102preview/storage/managed_cluster_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -81,6 +83,26 @@ func (cluster *ManagedCluster) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -7301,9 +7323,11 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Storage version of v1api20231102preview.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec @@ -7311,6 +7335,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -7323,6 +7365,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -7360,6 +7420,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap v20231001s.ManagedClusterOperatorConfigMaps @@ -7372,6 +7450,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20231001s.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen.go index 4cd3a179b26..d6034b7f802 100644 --- a/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen.go @@ -9,6 +9,9 @@ import ( v20240901s "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20240901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -80,6 +83,26 @@ func (pool *ManagedClustersAgentPool) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -286,14 +309,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -595,6 +619,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -955,6 +991,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec v20231001s.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -3245,6 +3293,136 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Storage version of v1api20231102preview.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *v20231001s.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *v20231001s.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20231102preview.PowerState type PowerState struct { Code *string `json:"code,omitempty"` @@ -3393,6 +3571,11 @@ type augmentConversionForLinuxOSConfig_STATUS interface { AssignPropertiesTo(dst *v20231001s.LinuxOSConfig_STATUS) error } +type augmentConversionForManagedClustersAgentPoolOperatorSpec interface { + AssignPropertiesFrom(src *v20231001s.ManagedClustersAgentPoolOperatorSpec) error + AssignPropertiesTo(dst *v20231001s.ManagedClustersAgentPoolOperatorSpec) error +} + type augmentConversionForPowerState interface { AssignPropertiesFrom(src *v20231001s.PowerState) error AssignPropertiesTo(dst *v20231001s.PowerState) error diff --git a/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen_test.go index 6a703969f93..426e23c521a 100644 --- a/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20231102preview/storage/managed_clusters_agent_pool_types_gen_test.go @@ -1927,6 +1927,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231001s.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2147,6 +2244,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20231102preview/storage/structure.txt b/v2/api/containerservice/v1api20231102preview/storage/structure.txt index 480feeb7b95..bff22939c5e 100644 --- a/v2/api/containerservice/v1api20231102preview/storage/structure.txt +++ b/v2/api/containerservice/v1api20231102preview/storage/structure.txt @@ -347,11 +347,13 @@ ManagedCluster: Resource │ ├── OidcIssuerProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -1030,7 +1032,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20231102preview.ManagedCluster -├── Spec: Object (53 properties) +├── Spec: Object (54 properties) │ ├── ArtifactStreamingProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag @@ -1122,6 +1124,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -1452,6 +1458,7 @@ augmentConversionForManagedClusterWorkloadAutoScalerProfile_STATUS: Interface augmentConversionForManagedCluster_STATUS: Interface augmentConversionForManagedCluster_Spec: Interface augmentConversionForManagedClustersAgentPool: Interface +augmentConversionForManagedClustersAgentPoolOperatorSpec: Interface augmentConversionForManagedClustersAgentPool_STATUS: Interface augmentConversionForManagedClustersAgentPool_Spec: Interface augmentConversionForPortRange: Interface diff --git a/v2/api/containerservice/v1api20231102preview/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20231102preview/storage/zz_generated.deepcopy.go index 704ae60bed0..485dbdc9990 100644 --- a/v2/api/containerservice/v1api20231102preview/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20231102preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -4687,6 +4688,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) @@ -4699,6 +4711,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -7161,6 +7184,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -7611,6 +7678,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20231102preview/structure.txt b/v2/api/containerservice/v1api20231102preview/structure.txt index 3e3a3d0e08e..25eae0d6cba 100644 --- a/v2/api/containerservice/v1api20231102preview/structure.txt +++ b/v2/api/containerservice/v1api20231102preview/structure.txt @@ -409,9 +409,11 @@ ManagedCluster: Resource │ │ └── "Unrestricted" │ ├── OidcIssuerProfile: *Object (1 property) │ │ └── Enabled: *bool -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── OIDCIssuerProfile: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -1093,7 +1095,7 @@ ManagedCluster: Resource └── Enabled: *bool ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (51 properties) +├── Spec: Object (52 properties) │ ├── ArtifactStreamingProfile: *Object (1 property) │ │ └── Enabled: *bool │ ├── AvailabilityZones: string[] @@ -1201,6 +1203,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 diff --git a/v2/api/containerservice/v1api20231102preview/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20231102preview/zz_generated.deepcopy.go index c161b7c854c..736798e35fb 100644 --- a/v2/api/containerservice/v1api20231102preview/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20231102preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20231102preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -3894,11 +3895,33 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -6030,6 +6053,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -6473,6 +6533,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) diff --git a/v2/api/containerservice/v1api20240402preview/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20240402preview/managed_cluster_types_gen.go index 5674e227548..629ff798a30 100644 --- a/v2/api/containerservice/v1api20240402preview/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/managed_cluster_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -269,13 +290,13 @@ func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnin if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + var toValidate []*genruntime.ConfigMapDestination + if cluster.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -297,14 +318,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -13747,9 +13768,15 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -13757,6 +13784,24 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -13769,6 +13814,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -13790,6 +13853,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -13802,6 +13883,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen.go index e9b12327bdb..06985de05c7 100644 --- a/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -444,6 +489,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: Both patch version and are supported. When is // specified, the latest supported patch version is chosen automatically. Updating the agent pool with the same // once it has been created will not trigger an upgrade, even if a newer patch version is available. As a @@ -1207,6 +1256,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1718,6 +1769,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -2153,6 +2216,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -6668,6 +6743,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The default is 'Ephemeral' if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, // defaults to 'Managed'. May not be changed after creation. For more information see [Ephemeral // OS](https://docs.microsoft.com/azure/aks/cluster-configuration#ephemeral-os). diff --git a/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen_test.go index 76fb0c1f8b5..268d9fe2536 100644 --- a/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20240402preview/managed_clusters_agent_pool_types_gen_test.go @@ -2511,6 +2511,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20240402ps.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2733,6 +2830,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20240402preview/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20240402preview/storage/managed_cluster_types_gen.go index 9767712a74c..4d78db53597 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/storage/managed_cluster_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -84,6 +86,26 @@ func (cluster *ManagedCluster) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -8065,9 +8087,11 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Storage version of v1api20240402preview.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec @@ -8075,6 +8099,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -8087,6 +8129,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -8124,6 +8184,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap v20231102ps.ManagedClusterOperatorConfigMaps @@ -8136,6 +8214,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20231102ps.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen.go index 7b099c0c71c..d653c939ffd 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231102preview/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (pool *ManagedClustersAgentPool) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -285,14 +308,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -581,6 +605,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -966,6 +1002,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -3660,6 +3708,136 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Storage version of v1api20240402preview.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForManagedClustersAgentPoolOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForManagedClustersAgentPoolOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20240402preview.PowerState // Describes the Power State of the cluster type PowerState struct { @@ -4105,6 +4283,11 @@ type augmentConversionForLinuxOSConfig_STATUS interface { AssignPropertiesTo(dst *storage.LinuxOSConfig_STATUS) error } +type augmentConversionForManagedClustersAgentPoolOperatorSpec interface { + AssignPropertiesFrom(src *storage.ManagedClustersAgentPoolOperatorSpec) error + AssignPropertiesTo(dst *storage.ManagedClustersAgentPoolOperatorSpec) error +} + type augmentConversionForPowerState interface { AssignPropertiesFrom(src *storage.PowerState) error AssignPropertiesTo(dst *storage.PowerState) error diff --git a/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen_test.go index cec8b7d3ad5..71128f8d51d 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20240402preview/storage/managed_clusters_agent_pool_types_gen_test.go @@ -2343,6 +2343,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231102ps.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2565,6 +2662,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20240402preview/storage/structure.txt b/v2/api/containerservice/v1api20240402preview/storage/structure.txt index 8b7f1b09000..7bbbd1cfcb0 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/structure.txt +++ b/v2/api/containerservice/v1api20240402preview/storage/structure.txt @@ -374,11 +374,13 @@ ManagedCluster: Resource │ ├── OidcIssuerProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -1084,7 +1086,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20240402preview.ManagedCluster -├── Spec: Object (55 properties) +├── Spec: Object (56 properties) │ ├── ArtifactStreamingProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag @@ -1179,6 +1181,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -1389,8 +1395,12 @@ ManagedClustersAgentPool: Resource └── WorkloadRuntime: *string TrustedAccessRoleBinding: Resource ├── Owner: containerservice/v1api20240402preview.ManagedCluster -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1579,6 +1589,7 @@ augmentConversionForManagedClusterWorkloadAutoScalerProfile_STATUS: Interface augmentConversionForManagedCluster_STATUS: Interface augmentConversionForManagedCluster_Spec: Interface augmentConversionForManagedClustersAgentPool: Interface +augmentConversionForManagedClustersAgentPoolOperatorSpec: Interface augmentConversionForManagedClustersAgentPool_STATUS: Interface augmentConversionForManagedClustersAgentPool_Spec: Interface augmentConversionForManualScaleProfile: Interface @@ -1601,6 +1612,7 @@ augmentConversionForSysctlConfig: Interface augmentConversionForSysctlConfig_STATUS: Interface augmentConversionForSystemData_STATUS: Interface augmentConversionForTrustedAccessRoleBinding: Interface +augmentConversionForTrustedAccessRoleBindingOperatorSpec: Interface augmentConversionForTrustedAccessRoleBinding_STATUS: Interface augmentConversionForTrustedAccessRoleBinding_Spec: Interface augmentConversionForUpgradeOverrideSettings: Interface diff --git a/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen.go index 0afba0e5744..514d9782f61 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen.go @@ -8,6 +8,9 @@ import ( v20231102ps "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20231102preview/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -79,6 +82,26 @@ func (binding *TrustedAccessRoleBinding) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrustedAccessRoleBinding{} // AzureName returns the Azure name of the resource @@ -249,8 +272,9 @@ type augmentConversionForTrustedAccessRoleBinding interface { type TrustedAccessRoleBinding_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -323,6 +347,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_From_TrustedAcces // AzureName binding.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrustedAccessRoleBindingOperatorSpec + err := operatorSpec.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + binding.OperatorSpec = &operatorSpec + } else { + binding.OperatorSpec = nil + } + // OriginalVersion binding.OriginalVersion = source.OriginalVersion @@ -373,6 +409,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_To_TrustedAccessR // AzureName destination.AzureName = binding.AzureName + // OperatorSpec + if binding.OperatorSpec != nil { + var operatorSpec v20231001s.TrustedAccessRoleBindingOperatorSpec + err := binding.OperatorSpec.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = binding.OriginalVersion @@ -614,6 +662,141 @@ type augmentConversionForTrustedAccessRoleBinding_STATUS interface { AssignPropertiesTo(dst *v20231001s.TrustedAccessRoleBinding_STATUS) error } +// Storage version of v1api20240402preview.TrustedAccessRoleBindingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrustedAccessRoleBindingOperatorSpec populates our TrustedAccessRoleBindingOperatorSpec from the provided source TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source *v20231001s.TrustedAccessRoleBindingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForTrustedAccessRoleBindingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForTrustedAccessRoleBindingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_TrustedAccessRoleBindingOperatorSpec populates the provided destination TrustedAccessRoleBindingOperatorSpec from our TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(destination *v20231001s.TrustedAccessRoleBindingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForTrustedAccessRoleBindingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForTrustedAccessRoleBindingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForTrustedAccessRoleBindingOperatorSpec interface { + AssignPropertiesFrom(src *v20231001s.TrustedAccessRoleBindingOperatorSpec) error + AssignPropertiesTo(dst *v20231001s.TrustedAccessRoleBindingOperatorSpec) error +} + func init() { SchemeBuilder.Register(&TrustedAccessRoleBinding{}, &TrustedAccessRoleBindingList{}) } diff --git a/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen_test.go index b3344aa9a9f..505ec1d06c3 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20240402preview/storage/trusted_access_role_binding_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrustedAccessRoleBindingOperatorSpec to TrustedAccessRoleBindingOperatorSpec via AssignProperties_To_TrustedAccessRoleBindingOperatorSpec & AssignProperties_From_TrustedAccessRoleBindingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec tests if a specific instance of TrustedAccessRoleBindingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20231001s.TrustedAccessRoleBindingOperatorSpec + err := copied.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrustedAccessRoleBindingOperatorSpec + err = actual.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -374,6 +471,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -383,6 +483,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -392,3 +498,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["OriginalVersion"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20240402preview/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20240402preview/storage/zz_generated.deepcopy.go index 58215ec69b8..534b64189fe 100644 --- a/v2/api/containerservice/v1api20240402preview/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20240402preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -5088,6 +5089,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) @@ -5100,6 +5112,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -7641,6 +7664,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -8111,6 +8178,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -9249,6 +9321,50 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -9316,6 +9432,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20240402preview/structure.txt b/v2/api/containerservice/v1api20240402preview/structure.txt index 23e047a1086..67e67398b29 100644 --- a/v2/api/containerservice/v1api20240402preview/structure.txt +++ b/v2/api/containerservice/v1api20240402preview/structure.txt @@ -443,9 +443,11 @@ ManagedCluster: Resource │ │ └── "Unrestricted" │ ├── OidcIssuerProfile: *Object (1 property) │ │ └── Enabled: *bool -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── OIDCIssuerProfile: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -1163,7 +1165,7 @@ ManagedCluster: Resource └── Enabled: *bool ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (53 properties) +├── Spec: Object (54 properties) │ ├── ArtifactStreamingProfile: *Object (1 property) │ │ └── Enabled: *bool │ ├── AvailabilityZones: string[] @@ -1276,6 +1278,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 @@ -1535,11 +1540,14 @@ ManagedClustersAgentPool: Resource └── "WasmWasi" TrustedAccessRoleBinding: Resource ├── Owner: ManagedCluster -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 24 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^([A-Za-z0-9-])+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Roles: string[] │ └── SourceResourceReference: *genruntime.ResourceReference diff --git a/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen.go index c61310fab76..a2924af2a7b 100644 --- a/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (binding *TrustedAccessRoleBinding) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrustedAccessRoleBinding resource func (binding *TrustedAccessRoleBinding) defaultImpl() { binding.defaultAzureName() } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrustedAccessRoleBinding{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (binding *TrustedAccessRoleBinding) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (binding *TrustedAccessRoleBinding) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference} + return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference, binding.validateSecretDestinations, binding.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (binding *TrustedAccessRoleBinding) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return binding.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (binding *TrustedAccessRoleBinding) validateConfigMapDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (binding *TrustedAccessRoleBinding) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (binding *TrustedAccessRoleBinding) validateSecretDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (binding *TrustedAccessRoleBinding) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrustedAccessRoleBinding) @@ -336,6 +381,10 @@ type TrustedAccessRoleBinding_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -397,6 +446,8 @@ func (binding *TrustedAccessRoleBinding_Spec) PopulateFromARM(owner genruntime.A // Set property "AzureName": binding.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": binding.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -473,6 +524,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_From_TrustedAcces // AzureName binding.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrustedAccessRoleBindingOperatorSpec + err := operatorSpec.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + binding.OperatorSpec = &operatorSpec + } else { + binding.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_To_TrustedAccessR // AzureName destination.AzureName = binding.AzureName + // OperatorSpec + if binding.OperatorSpec != nil { + var operatorSpec storage.TrustedAccessRoleBindingOperatorSpec + err := binding.OperatorSpec.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = binding.OriginalVersion() @@ -802,6 +877,110 @@ func (binding *TrustedAccessRoleBinding_STATUS) AssignProperties_To_TrustedAcces return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrustedAccessRoleBindingOperatorSpec populates our TrustedAccessRoleBindingOperatorSpec from the provided source TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source *storage.TrustedAccessRoleBindingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrustedAccessRoleBindingOperatorSpec populates the provided destination TrustedAccessRoleBindingOperatorSpec from our TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(destination *storage.TrustedAccessRoleBindingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type TrustedAccessRoleBindingProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen_test.go index a4933ca6983..9b559d774fb 100644 --- a/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20240402preview/trusted_access_role_binding_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrustedAccessRoleBindingOperatorSpec to TrustedAccessRoleBindingOperatorSpec via AssignProperties_To_TrustedAccessRoleBindingOperatorSpec & AssignProperties_From_TrustedAccessRoleBindingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec tests if a specific instance of TrustedAccessRoleBindingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20240402ps.TrustedAccessRoleBindingOperatorSpec + err := copied.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrustedAccessRoleBindingOperatorSpec + err = actual.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -379,6 +476,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -388,6 +488,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -396,3 +502,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["AzureName"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20240402preview/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20240402preview/zz_generated.deepcopy.go index 1b7a8712483..c7c7806d388 100644 --- a/v2/api/containerservice/v1api20240402preview/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20240402preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20240402preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -4225,11 +4226,33 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -6426,6 +6449,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -6889,6 +6949,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -7887,6 +7952,43 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -7947,6 +8049,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen.go b/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen.go index 4ecd44f3e7a..60ad3422f29 100644 --- a/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen.go +++ b/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (configuration *MaintenanceConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the MaintenanceConfiguration resource func (configuration *MaintenanceConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &MaintenanceConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *MaintenanceConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MaintenanceConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *MaintenanceConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MaintenanceConfiguration{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (configuration *MaintenanceConfiguration) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (configuration *MaintenanceConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (configuration *MaintenanceConfiguration) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *MaintenanceConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (configuration *MaintenanceConfiguration) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *MaintenanceConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *MaintenanceConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MaintenanceConfiguration) @@ -341,6 +386,10 @@ type MaintenanceConfiguration_Spec struct { // NotAllowedTime: Time slots on which upgrade is not allowed. NotAllowedTime []TimeSpan `json:"notAllowedTime,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MaintenanceConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -437,6 +486,8 @@ func (configuration *MaintenanceConfiguration_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -546,6 +597,18 @@ func (configuration *MaintenanceConfiguration_Spec) AssignProperties_From_Mainte configuration.NotAllowedTime = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MaintenanceConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_MaintenanceConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MaintenanceConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -614,6 +677,18 @@ func (configuration *MaintenanceConfiguration_Spec) AssignProperties_To_Maintena destination.NotAllowedTime = nil } + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.MaintenanceConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_MaintenanceConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MaintenanceConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -1052,6 +1127,110 @@ func (configuration *MaintenanceConfiguration_STATUS) AssignProperties_To_Mainte return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MaintenanceConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MaintenanceConfigurationOperatorSpec populates our MaintenanceConfigurationOperatorSpec from the provided source MaintenanceConfigurationOperatorSpec +func (operator *MaintenanceConfigurationOperatorSpec) AssignProperties_From_MaintenanceConfigurationOperatorSpec(source *storage.MaintenanceConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MaintenanceConfigurationOperatorSpec populates the provided destination MaintenanceConfigurationOperatorSpec from our MaintenanceConfigurationOperatorSpec +func (operator *MaintenanceConfigurationOperatorSpec) AssignProperties_To_MaintenanceConfigurationOperatorSpec(destination *storage.MaintenanceConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Maintenance window used to configure scheduled auto-upgrade for a Managed Cluster. type MaintenanceWindow struct { // +kubebuilder:validation:Required diff --git a/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen_test.go b/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen_test.go index 34e810cf206..7713eeee033 100644 --- a/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/maintenance_configuration_types_gen_test.go @@ -784,6 +784,103 @@ func AddRelatedPropertyGeneratorsForMaintenanceConfiguration(gens map[string]gop gens["Status"] = MaintenanceConfiguration_STATUSGenerator() } +func Test_MaintenanceConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MaintenanceConfigurationOperatorSpec to MaintenanceConfigurationOperatorSpec via AssignProperties_To_MaintenanceConfigurationOperatorSpec & AssignProperties_From_MaintenanceConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMaintenanceConfigurationOperatorSpec, MaintenanceConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMaintenanceConfigurationOperatorSpec tests if a specific instance of MaintenanceConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMaintenanceConfigurationOperatorSpec(subject MaintenanceConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MaintenanceConfigurationOperatorSpec + err := copied.AssignProperties_To_MaintenanceConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MaintenanceConfigurationOperatorSpec + err = actual.AssignProperties_From_MaintenanceConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MaintenanceConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MaintenanceConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec, MaintenanceConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec runs a test to see if a specific instance of MaintenanceConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec(subject MaintenanceConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MaintenanceConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MaintenanceConfigurationOperatorSpec instances for property testing - lazily instantiated by +// MaintenanceConfigurationOperatorSpecGenerator() +var maintenanceConfigurationOperatorSpecGenerator gopter.Gen + +// MaintenanceConfigurationOperatorSpecGenerator returns a generator of MaintenanceConfigurationOperatorSpec instances for property testing. +func MaintenanceConfigurationOperatorSpecGenerator() gopter.Gen { + if maintenanceConfigurationOperatorSpecGenerator != nil { + return maintenanceConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + maintenanceConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MaintenanceConfigurationOperatorSpec{}), generators) + + return maintenanceConfigurationOperatorSpecGenerator +} + func Test_MaintenanceConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1022,6 +1119,7 @@ func AddIndependentPropertyGeneratorsForMaintenanceConfiguration_Spec(gens map[s func AddRelatedPropertyGeneratorsForMaintenanceConfiguration_Spec(gens map[string]gopter.Gen) { gens["MaintenanceWindow"] = gen.PtrOf(MaintenanceWindowGenerator()) gens["NotAllowedTime"] = gen.SliceOf(TimeSpanGenerator()) + gens["OperatorSpec"] = gen.PtrOf(MaintenanceConfigurationOperatorSpecGenerator()) gens["TimeInWeek"] = gen.SliceOf(TimeInWeekGenerator()) } diff --git a/v2/api/containerservice/v1api20240901/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20240901/managed_cluster_types_gen.go index acd63fb1183..d1295f6bd99 100644 --- a/v2/api/containerservice/v1api20240901/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20240901/managed_cluster_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -97,6 +98,26 @@ func (cluster *ManagedCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedCluster resource func (cluster *ManagedCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ManagedCluster{} // InitializeSpec initializes the spec for this resource from the given status @@ -266,13 +287,13 @@ func (cluster *ManagedCluster) validateConfigMapDestinations() (admission.Warnin if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + var toValidate []*genruntime.ConfigMapDestination + if cluster.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + cluster.Spec.OperatorSpec.ConfigMaps.OIDCIssuerProfile, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -294,14 +315,14 @@ func (cluster *ManagedCluster) validateSecretDestinations() (admission.Warnings, if cluster.Spec.OperatorSpec == nil { return nil, nil } - if cluster.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - cluster.Spec.OperatorSpec.Secrets.AdminCredentials, - cluster.Spec.OperatorSpec.Secrets.UserCredentials, + var toValidate []*genruntime.SecretDestination + if cluster.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + cluster.Spec.OperatorSpec.Secrets.AdminCredentials, + cluster.Spec.OperatorSpec.Secrets.UserCredentials, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(cluster, toValidate, cluster.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -12518,9 +12539,15 @@ func (profile *ManagedClusterOIDCIssuerProfile_STATUS) AssignProperties_To_Manag // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } @@ -12528,6 +12555,24 @@ type ManagedClusterOperatorSpec struct { // AssignProperties_From_ManagedClusterOperatorSpec populates our ManagedClusterOperatorSpec from the provided source ManagedClusterOperatorSpec func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedClusterOperatorSpec(source *storage.ManagedClusterOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ManagedClusterOperatorConfigMaps @@ -12540,6 +12585,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_From_ManagedCluster operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ManagedClusterOperatorSecrets @@ -12561,6 +12624,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ManagedClusterOperatorConfigMaps @@ -12573,6 +12654,24 @@ func (operator *ManagedClusterOperatorSpec) AssignProperties_To_ManagedClusterOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ManagedClusterOperatorSecrets diff --git a/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen.go index 204797c3348..f42b0e2c7f2 100644 --- a/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (pool *ManagedClustersAgentPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ManagedClustersAgentPool resource func (pool *ManagedClustersAgentPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ManagedClustersAgentPool{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (pool *ManagedClustersAgentPool) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (pool *ManagedClustersAgentPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (pool *ManagedClustersAgentPool) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ManagedClustersAgentPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (pool *ManagedClustersAgentPool) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ManagedClustersAgentPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ManagedClustersAgentPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ManagedClustersAgentPool) @@ -414,6 +459,10 @@ type ManagedClustersAgentPool_Spec struct { // NodeTaints: The taints added to new nodes during node pool create and scale. For example, key=value:NoSchedule. NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + // OrchestratorVersion: Both patch version (e.g. 1.20.13) and (e.g. 1.20) are supported. // When is specified, the latest supported GA patch version is chosen automatically. Updating the cluster // with the same once it has been created (e.g. 1.14.x -> 1.14) will not trigger an upgrade, even if a newer @@ -1036,6 +1085,8 @@ func (pool *ManagedClustersAgentPool_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "OrchestratorVersion": // copying flattened property: if typedInput.Properties != nil { @@ -1459,6 +1510,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_From_ManagedClusters // NodeTaints pool.NodeTaints = genruntime.CloneSliceOfString(source.NodeTaints) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ManagedClustersAgentPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // OrchestratorVersion pool.OrchestratorVersion = genruntime.ClonePointerToString(source.OrchestratorVersion) @@ -1805,6 +1868,18 @@ func (pool *ManagedClustersAgentPool_Spec) AssignProperties_To_ManagedClustersAg // NodeTaints destination.NodeTaints = genruntime.CloneSliceOfString(pool.NodeTaints) + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ManagedClustersAgentPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ManagedClustersAgentPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OrchestratorVersion destination.OrchestratorVersion = genruntime.ClonePointerToString(pool.OrchestratorVersion) @@ -5986,6 +6061,110 @@ func (config *LinuxOSConfig_STATUS) AssignProperties_To_LinuxOSConfig_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ManagedClustersAgentPoolOperatorSpec populates our ManagedClustersAgentPoolOperatorSpec from the provided source ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(source *storage.ManagedClustersAgentPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ManagedClustersAgentPoolOperatorSpec populates the provided destination ManagedClustersAgentPoolOperatorSpec from our ManagedClustersAgentPoolOperatorSpec +func (operator *ManagedClustersAgentPoolOperatorSpec) AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(destination *storage.ManagedClustersAgentPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The default is 'Ephemeral' if the VM supports it and has a cache disk larger than the requested OSDiskSizeGB. Otherwise, // defaults to 'Managed'. May not be changed after creation. For more information see [Ephemeral // OS](https://docs.microsoft.com/azure/aks/cluster-configuration#ephemeral-os). diff --git a/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen_test.go index c6f96a283fc..2d8411fa29c 100644 --- a/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/managed_clusters_agent_pool_types_gen_test.go @@ -1878,6 +1878,103 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ManagedClustersAgentPoolOperatorSpec to ManagedClustersAgentPoolOperatorSpec via AssignProperties_To_ManagedClustersAgentPoolOperatorSpec & AssignProperties_From_ManagedClustersAgentPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec tests if a specific instance of ManagedClustersAgentPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ManagedClustersAgentPoolOperatorSpec + err := copied.AssignProperties_To_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ManagedClustersAgentPoolOperatorSpec + err = actual.AssignProperties_From_ManagedClustersAgentPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2218,6 +2315,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen.go b/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen.go index 8f44bc86247..a2042d484a9 100644 --- a/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen.go +++ b/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (configuration *MaintenanceConfiguration) SetConditions(conditions conditio configuration.Status.Conditions = conditions } +var _ configmaps.Exporter = &MaintenanceConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *MaintenanceConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MaintenanceConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *MaintenanceConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MaintenanceConfiguration{} // AzureName returns the Azure name of the resource @@ -148,10 +171,11 @@ const APIVersion_Value = APIVersion("2024-09-01") type MaintenanceConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - MaintenanceWindow *MaintenanceWindow `json:"maintenanceWindow,omitempty"` - NotAllowedTime []TimeSpan `json:"notAllowedTime,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + MaintenanceWindow *MaintenanceWindow `json:"maintenanceWindow,omitempty"` + NotAllowedTime []TimeSpan `json:"notAllowedTime,omitempty"` + OperatorSpec *MaintenanceConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -215,6 +239,14 @@ func (configuration *MaintenanceConfiguration_STATUS) ConvertStatusTo(destinatio return destination.ConvertStatusFrom(configuration) } +// Storage version of v1api20240901.MaintenanceConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MaintenanceConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240901.MaintenanceWindow // Maintenance window used to configure scheduled auto-upgrade for a Managed Cluster. type MaintenanceWindow struct { diff --git a/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen_test.go b/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen_test.go index e70cc8a3b56..0061265cbea 100644 --- a/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/storage/maintenance_configuration_types_gen_test.go @@ -446,6 +446,61 @@ func AddRelatedPropertyGeneratorsForMaintenanceConfiguration(gens map[string]gop gens["Status"] = MaintenanceConfiguration_STATUSGenerator() } +func Test_MaintenanceConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MaintenanceConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec, MaintenanceConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec runs a test to see if a specific instance of MaintenanceConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMaintenanceConfigurationOperatorSpec(subject MaintenanceConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MaintenanceConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MaintenanceConfigurationOperatorSpec instances for property testing - lazily instantiated by +// MaintenanceConfigurationOperatorSpecGenerator() +var maintenanceConfigurationOperatorSpecGenerator gopter.Gen + +// MaintenanceConfigurationOperatorSpecGenerator returns a generator of MaintenanceConfigurationOperatorSpec instances for property testing. +func MaintenanceConfigurationOperatorSpecGenerator() gopter.Gen { + if maintenanceConfigurationOperatorSpecGenerator != nil { + return maintenanceConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + maintenanceConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MaintenanceConfigurationOperatorSpec{}), generators) + + return maintenanceConfigurationOperatorSpecGenerator +} + func Test_MaintenanceConfiguration_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -601,6 +656,7 @@ func AddIndependentPropertyGeneratorsForMaintenanceConfiguration_Spec(gens map[s func AddRelatedPropertyGeneratorsForMaintenanceConfiguration_Spec(gens map[string]gopter.Gen) { gens["MaintenanceWindow"] = gen.PtrOf(MaintenanceWindowGenerator()) gens["NotAllowedTime"] = gen.SliceOf(TimeSpanGenerator()) + gens["OperatorSpec"] = gen.PtrOf(MaintenanceConfigurationOperatorSpecGenerator()) gens["TimeInWeek"] = gen.SliceOf(TimeInWeekGenerator()) } diff --git a/v2/api/containerservice/v1api20240901/storage/managed_cluster_types_gen.go b/v2/api/containerservice/v1api20240901/storage/managed_cluster_types_gen.go index f568ca9e06d..ff4a499c0fe 100644 --- a/v2/api/containerservice/v1api20240901/storage/managed_cluster_types_gen.go +++ b/v2/api/containerservice/v1api20240901/storage/managed_cluster_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (cluster *ManagedCluster) SetConditions(conditions conditions.Conditions) { cluster.Status.Conditions = conditions } +var _ configmaps.Exporter = &ManagedCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *ManagedCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *ManagedCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &ManagedCluster{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -726,9 +748,11 @@ type ManagedClusterOIDCIssuerProfile_STATUS struct { // Storage version of v1api20240901.ManagedClusterOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ManagedClusterOperatorSpec struct { - ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ManagedClusterOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ManagedClusterOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20240901.ManagedClusterPodIdentityProfile diff --git a/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen.go b/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen.go index 06b5e82e3f3..392306236e0 100644 --- a/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen.go +++ b/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (pool *ManagedClustersAgentPool) SetConditions(conditions conditions.Condit pool.Status.Conditions = conditions } +var _ configmaps.Exporter = &ManagedClustersAgentPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ManagedClustersAgentPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ManagedClustersAgentPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ManagedClustersAgentPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ManagedClustersAgentPool{} // AzureName returns the Azure name of the resource @@ -173,14 +196,15 @@ type ManagedClustersAgentPool_Spec struct { // NodePublicIPPrefixReference: This is of the form: // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/publicIPPrefixes/{publicIPPrefixName} - NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` - NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` - OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` - OsDiskType *string `json:"osDiskType,omitempty"` - OsSKU *string `json:"osSKU,omitempty"` - OsType *string `json:"osType,omitempty"` + NodePublicIPPrefixReference *genruntime.ResourceReference `armReference:"NodePublicIPPrefixID" json:"nodePublicIPPrefixReference,omitempty"` + NodeTaints []string `json:"nodeTaints,omitempty" serializationType:"explicitEmptyCollection"` + OperatorSpec *ManagedClustersAgentPoolOperatorSpec `json:"operatorSpec,omitempty"` + OrchestratorVersion *string `json:"orchestratorVersion,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OsDiskSizeGB *int `json:"osDiskSizeGB,omitempty"` + OsDiskType *string `json:"osDiskType,omitempty"` + OsSKU *string `json:"osSKU,omitempty"` + OsType *string `json:"osType,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -446,6 +470,14 @@ type LinuxOSConfig_STATUS struct { TransparentHugePageEnabled *string `json:"transparentHugePageEnabled,omitempty"` } +// Storage version of v1api20240901.ManagedClustersAgentPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ManagedClustersAgentPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240901.PowerState // Describes the Power State of the cluster type PowerState struct { diff --git a/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen_test.go b/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen_test.go index ac682f2c576..c6c71353294 100644 --- a/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/storage/managed_clusters_agent_pool_types_gen_test.go @@ -1120,6 +1120,61 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool(gens map[string]gop gens["Status"] = ManagedClustersAgentPool_STATUSGenerator() } +func Test_ManagedClustersAgentPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ManagedClustersAgentPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec, ManagedClustersAgentPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec runs a test to see if a specific instance of ManagedClustersAgentPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForManagedClustersAgentPoolOperatorSpec(subject ManagedClustersAgentPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ManagedClustersAgentPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ManagedClustersAgentPoolOperatorSpec instances for property testing - lazily instantiated by +// ManagedClustersAgentPoolOperatorSpecGenerator() +var managedClustersAgentPoolOperatorSpecGenerator gopter.Gen + +// ManagedClustersAgentPoolOperatorSpecGenerator returns a generator of ManagedClustersAgentPoolOperatorSpec instances for property testing. +func ManagedClustersAgentPoolOperatorSpecGenerator() gopter.Gen { + if managedClustersAgentPoolOperatorSpecGenerator != nil { + return managedClustersAgentPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + managedClustersAgentPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ManagedClustersAgentPoolOperatorSpec{}), generators) + + return managedClustersAgentPoolOperatorSpecGenerator +} + func Test_ManagedClustersAgentPool_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1297,6 +1352,7 @@ func AddRelatedPropertyGeneratorsForManagedClustersAgentPool_Spec(gens map[strin gens["KubeletConfig"] = gen.PtrOf(KubeletConfigGenerator()) gens["LinuxOSConfig"] = gen.PtrOf(LinuxOSConfigGenerator()) gens["NetworkProfile"] = gen.PtrOf(AgentPoolNetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ManagedClustersAgentPoolOperatorSpecGenerator()) gens["PowerState"] = gen.PtrOf(PowerStateGenerator()) gens["SecurityProfile"] = gen.PtrOf(AgentPoolSecurityProfileGenerator()) gens["UpgradeSettings"] = gen.PtrOf(AgentPoolUpgradeSettingsGenerator()) diff --git a/v2/api/containerservice/v1api20240901/storage/structure.txt b/v2/api/containerservice/v1api20240901/storage/structure.txt index fb03db96276..7251adb2de7 100644 --- a/v2/api/containerservice/v1api20240901/storage/structure.txt +++ b/v2/api/containerservice/v1api20240901/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2024-09-01" MaintenanceConfiguration: Resource ├── Owner: containerservice/v1api20240901.ManagedCluster -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── MaintenanceWindow: *Object (7 properties) │ │ ├── DurationHours: *int @@ -39,6 +39,10 @@ MaintenanceConfiguration: Resource │ │ ├── End: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Start: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -387,11 +391,13 @@ ManagedCluster: Resource │ ├── OidcIssuerProfile: *Object (2 properties) │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── OIDCIssuerProfile: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ ├── PropertyBag: genruntime.PropertyBag @@ -987,7 +993,7 @@ ManagedCluster: Resource └── PropertyBag: genruntime.PropertyBag ManagedClustersAgentPool: Resource ├── Owner: containerservice/v1api20240901.ManagedCluster -├── Spec: Object (46 properties) +├── Spec: Object (47 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: string │ ├── CapacityReservationGroupReference: *genruntime.ResourceReference @@ -1070,6 +1076,10 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OriginalVersion: string │ ├── OsDiskSizeGB: *int @@ -1228,8 +1238,12 @@ ManagedClustersAgentPool: Resource └── WorkloadRuntime: *string TrustedAccessRoleBinding: Resource ├── Owner: containerservice/v1api20240901.ManagedCluster -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen.go index e143175628f..9e90af20be9 100644 --- a/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (binding *TrustedAccessRoleBinding) SetConditions(conditions conditions.Con binding.Status.Conditions = conditions } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrustedAccessRoleBinding{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type TrustedAccessRoleBindingList struct { type TrustedAccessRoleBinding_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -211,6 +235,14 @@ func (binding *TrustedAccessRoleBinding_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(binding) } +// Storage version of v1api20240901.TrustedAccessRoleBindingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&TrustedAccessRoleBinding{}, &TrustedAccessRoleBindingList{}) } diff --git a/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen_test.go index 732fd19bba7..6d2694fcf2c 100644 --- a/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/storage/trusted_access_role_binding_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -203,6 +258,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -212,6 +270,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["OriginalVersion"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20240901/storage/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20240901/storage/zz_generated.deepcopy.go index 9ad7e4ac660..63c5b9a1e8c 100644 --- a/v2/api/containerservice/v1api20240901/storage/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20240901/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -2146,6 +2147,50 @@ func (in *MaintenanceConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MaintenanceConfigurationOperatorSpec) DeepCopyInto(out *MaintenanceConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceConfigurationOperatorSpec. +func (in *MaintenanceConfigurationOperatorSpec) DeepCopy() *MaintenanceConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(MaintenanceConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MaintenanceConfiguration_STATUS) DeepCopyInto(out *MaintenanceConfiguration_STATUS) { *out = *in @@ -2229,6 +2274,11 @@ func (in *MaintenanceConfiguration_Spec) DeepCopyInto(out *MaintenanceConfigurat (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MaintenanceConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4510,6 +4560,17 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) @@ -4522,6 +4583,17 @@ func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -6781,6 +6853,50 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -7174,6 +7290,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -8366,6 +8487,50 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -8433,6 +8598,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/containerservice/v1api20240901/structure.txt b/v2/api/containerservice/v1api20240901/structure.txt index 0e5ae7b27b4..7d53ac143ce 100644 --- a/v2/api/containerservice/v1api20240901/structure.txt +++ b/v2/api/containerservice/v1api20240901/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2024-09-01" MaintenanceConfiguration: Resource ├── Owner: ManagedCluster -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── MaintenanceWindow: *Object (6 properties) │ │ ├── DurationHours: Validated<*int> (2 rules) @@ -64,6 +64,9 @@ MaintenanceConfiguration: Resource │ ├── NotAllowedTime: Object (2 properties)[] │ │ ├── End: *string │ │ └── Start: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── TimeInWeek: Object (2 properties)[] │ ├── Day: *Enum (7 values) @@ -503,9 +506,11 @@ ManagedCluster: Resource │ │ └── "Unrestricted" │ ├── OidcIssuerProfile: *Object (1 property) │ │ └── Enabled: *bool -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── OIDCIssuerProfile: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── AdminCredentials: *genruntime.SecretDestination │ │ └── UserCredentials: *genruntime.SecretDestination @@ -1098,7 +1103,7 @@ ManagedCluster: Resource └── Enabled: *bool ManagedClustersAgentPool: Resource ├── Owner: ManagedCluster -├── Spec: Object (44 properties) +├── Spec: Object (45 properties) │ ├── AvailabilityZones: string[] │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 12 @@ -1199,6 +1204,9 @@ ManagedClustersAgentPool: Resource │ ├── NodeLabels: map[string]string │ ├── NodePublicIPPrefixReference: *genruntime.ResourceReference │ ├── NodeTaints: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OrchestratorVersion: *string │ ├── OsDiskSizeGB: *Validated (2 rules) │ │ ├── Rule 0: Maximum: 2048 @@ -1398,11 +1406,14 @@ ManagedClustersAgentPool: Resource └── "WasmWasi" TrustedAccessRoleBinding: Resource ├── Owner: ManagedCluster -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 24 │ │ ├── Rule 1: MinLength: 1 │ │ └── Rule 2: Pattern: "^([A-Za-z0-9-])+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Roles: string[] │ └── SourceResourceReference: *genruntime.ResourceReference diff --git a/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen.go b/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen.go index 6a83e0ec295..8c9f708a67d 100644 --- a/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen.go +++ b/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (binding *TrustedAccessRoleBinding) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrustedAccessRoleBinding resource func (binding *TrustedAccessRoleBinding) defaultImpl() { binding.defaultAzureName() } +var _ configmaps.Exporter = &TrustedAccessRoleBinding{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (binding *TrustedAccessRoleBinding) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrustedAccessRoleBinding{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (binding *TrustedAccessRoleBinding) SecretDestinationExpressions() []*core.DestinationExpression { + if binding.Spec.OperatorSpec == nil { + return nil + } + return binding.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &TrustedAccessRoleBinding{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (binding *TrustedAccessRoleBinding) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (binding *TrustedAccessRoleBinding) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference} + return []func() (admission.Warnings, error){binding.validateResourceReferences, binding.validateOwnerReference, binding.validateSecretDestinations, binding.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (binding *TrustedAccessRoleBinding) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return binding.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return binding.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (binding *TrustedAccessRoleBinding) validateConfigMapDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (binding *TrustedAccessRoleBinding) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (binding *TrustedAccessRoleBinding) validateSecretDestinations() (admission.Warnings, error) { + if binding.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(binding, nil, binding.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (binding *TrustedAccessRoleBinding) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrustedAccessRoleBinding) @@ -333,6 +378,10 @@ type TrustedAccessRoleBinding_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrustedAccessRoleBindingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -394,6 +443,8 @@ func (binding *TrustedAccessRoleBinding_Spec) PopulateFromARM(owner genruntime.A // Set property "AzureName": binding.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": binding.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -470,6 +521,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_From_TrustedAcces // AzureName binding.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrustedAccessRoleBindingOperatorSpec + err := operatorSpec.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + binding.OperatorSpec = &operatorSpec + } else { + binding.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -501,6 +564,18 @@ func (binding *TrustedAccessRoleBinding_Spec) AssignProperties_To_TrustedAccessR // AzureName destination.AzureName = binding.AzureName + // OperatorSpec + if binding.OperatorSpec != nil { + var operatorSpec storage.TrustedAccessRoleBindingOperatorSpec + err := binding.OperatorSpec.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrustedAccessRoleBindingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = binding.OriginalVersion() @@ -817,6 +892,110 @@ func (binding *TrustedAccessRoleBinding_STATUS) AssignProperties_To_TrustedAcces return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrustedAccessRoleBindingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrustedAccessRoleBindingOperatorSpec populates our TrustedAccessRoleBindingOperatorSpec from the provided source TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(source *storage.TrustedAccessRoleBindingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrustedAccessRoleBindingOperatorSpec populates the provided destination TrustedAccessRoleBindingOperatorSpec from our TrustedAccessRoleBindingOperatorSpec +func (operator *TrustedAccessRoleBindingOperatorSpec) AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(destination *storage.TrustedAccessRoleBindingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type TrustedAccessRoleBindingProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen_test.go b/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen_test.go index fbd67989406..a1c5c4f0d43 100644 --- a/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen_test.go +++ b/v2/api/containerservice/v1api20240901/trusted_access_role_binding_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding(gens map[string]gop gens["Status"] = TrustedAccessRoleBinding_STATUSGenerator() } +func Test_TrustedAccessRoleBindingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrustedAccessRoleBindingOperatorSpec to TrustedAccessRoleBindingOperatorSpec via AssignProperties_To_TrustedAccessRoleBindingOperatorSpec & AssignProperties_From_TrustedAccessRoleBindingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec tests if a specific instance of TrustedAccessRoleBindingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.TrustedAccessRoleBindingOperatorSpec + err := copied.AssignProperties_To_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrustedAccessRoleBindingOperatorSpec + err = actual.AssignProperties_From_TrustedAccessRoleBindingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrustedAccessRoleBindingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrustedAccessRoleBindingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec, TrustedAccessRoleBindingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec runs a test to see if a specific instance of TrustedAccessRoleBindingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrustedAccessRoleBindingOperatorSpec(subject TrustedAccessRoleBindingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrustedAccessRoleBindingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrustedAccessRoleBindingOperatorSpec instances for property testing - lazily instantiated by +// TrustedAccessRoleBindingOperatorSpecGenerator() +var trustedAccessRoleBindingOperatorSpecGenerator gopter.Gen + +// TrustedAccessRoleBindingOperatorSpecGenerator returns a generator of TrustedAccessRoleBindingOperatorSpec instances for property testing. +func TrustedAccessRoleBindingOperatorSpecGenerator() gopter.Gen { + if trustedAccessRoleBindingOperatorSpecGenerator != nil { + return trustedAccessRoleBindingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trustedAccessRoleBindingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBindingOperatorSpec{}), generators) + + return trustedAccessRoleBindingOperatorSpecGenerator +} + func Test_TrustedAccessRoleBinding_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -378,6 +475,9 @@ func RunJSONSerializationTestForTrustedAccessRoleBinding_Spec(subject TrustedAcc var trustedAccessRoleBinding_SpecGenerator gopter.Gen // TrustedAccessRoleBinding_SpecGenerator returns a generator of TrustedAccessRoleBinding_Spec instances for property testing. +// We first initialize trustedAccessRoleBinding_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { if trustedAccessRoleBinding_SpecGenerator != nil { return trustedAccessRoleBinding_SpecGenerator @@ -387,6 +487,12 @@ func TrustedAccessRoleBinding_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(generators) + trustedAccessRoleBinding_SpecGenerator = gen.Struct(reflect.TypeOf(TrustedAccessRoleBinding_Spec{}), generators) + return trustedAccessRoleBinding_SpecGenerator } @@ -395,3 +501,8 @@ func AddIndependentPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[s gens["AzureName"] = gen.AlphaString() gens["Roles"] = gen.SliceOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForTrustedAccessRoleBinding_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(TrustedAccessRoleBindingOperatorSpecGenerator()) +} diff --git a/v2/api/containerservice/v1api20240901/zz_generated.deepcopy.go b/v2/api/containerservice/v1api20240901/zz_generated.deepcopy.go index 387ad8b2997..c007d79c731 100644 --- a/v2/api/containerservice/v1api20240901/zz_generated.deepcopy.go +++ b/v2/api/containerservice/v1api20240901/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20240901 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1754,6 +1755,43 @@ func (in *MaintenanceConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MaintenanceConfigurationOperatorSpec) DeepCopyInto(out *MaintenanceConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceConfigurationOperatorSpec. +func (in *MaintenanceConfigurationOperatorSpec) DeepCopy() *MaintenanceConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(MaintenanceConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MaintenanceConfiguration_STATUS) DeepCopyInto(out *MaintenanceConfiguration_STATUS) { *out = *in @@ -1830,6 +1868,11 @@ func (in *MaintenanceConfiguration_Spec) DeepCopyInto(out *MaintenanceConfigurat (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MaintenanceConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3759,11 +3802,33 @@ func (in *ManagedClusterOperatorSecrets) DeepCopy() *ManagedClusterOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClusterOperatorSpec) DeepCopyInto(out *ManagedClusterOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ManagedClusterOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ManagedClusterOperatorSecrets) @@ -5701,6 +5766,43 @@ func (in *ManagedClustersAgentPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopyInto(out *ManagedClustersAgentPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedClustersAgentPoolOperatorSpec. +func (in *ManagedClustersAgentPoolOperatorSpec) DeepCopy() *ManagedClustersAgentPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ManagedClustersAgentPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedClustersAgentPool_STATUS) DeepCopyInto(out *ManagedClustersAgentPool_STATUS) { *out = *in @@ -6087,6 +6189,11 @@ func (in *ManagedClustersAgentPool_Spec) DeepCopyInto(out *ManagedClustersAgentP *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ManagedClustersAgentPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OrchestratorVersion != nil { in, out := &in.OrchestratorVersion, &out.OrchestratorVersion *out = new(string) @@ -7125,6 +7232,43 @@ func (in *TrustedAccessRoleBindingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopyInto(out *TrustedAccessRoleBindingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedAccessRoleBindingOperatorSpec. +func (in *TrustedAccessRoleBindingOperatorSpec) DeepCopy() *TrustedAccessRoleBindingOperatorSpec { + if in == nil { + return nil + } + out := new(TrustedAccessRoleBindingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_STATUS) DeepCopyInto(out *TrustedAccessRoleBinding_STATUS) { *out = *in @@ -7185,6 +7329,11 @@ func (in *TrustedAccessRoleBinding_STATUS) DeepCopy() *TrustedAccessRoleBinding_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrustedAccessRoleBinding_Spec) DeepCopyInto(out *TrustedAccessRoleBinding_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrustedAccessRoleBindingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/datafactory/v1api20180601/factory_types_gen.go b/v2/api/datafactory/v1api20180601/factory_types_gen.go index ee306669590..3f817a0eea3 100644 --- a/v2/api/datafactory/v1api20180601/factory_types_gen.go +++ b/v2/api/datafactory/v1api20180601/factory_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (factory *Factory) defaultAzureName() { // defaultImpl applies the code generated defaults to the Factory resource func (factory *Factory) defaultImpl() { factory.defaultAzureName() } +var _ configmaps.Exporter = &Factory{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (factory *Factory) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if factory.Spec.OperatorSpec == nil { + return nil + } + return factory.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Factory{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (factory *Factory) SecretDestinationExpressions() []*core.DestinationExpression { + if factory.Spec.OperatorSpec == nil { + return nil + } + return factory.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Factory{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (factory *Factory) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (factory *Factory) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){factory.validateResourceReferences, factory.validateOwnerReference} + return []func() (admission.Warnings, error){factory.validateResourceReferences, factory.validateOwnerReference, factory.validateSecretDestinations, factory.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (factory *Factory) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return factory.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return factory.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return factory.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (factory *Factory) validateConfigMapDestinations() (admission.Warnings, error) { + if factory.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(factory, nil, factory.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (factory *Factory) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (factory *Factory) validateSecretDestinations() (admission.Warnings, error) { + if factory.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(factory, nil, factory.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (factory *Factory) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Factory) @@ -353,6 +398,10 @@ type Factory_Spec struct { // Location: The resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FactoryOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -537,6 +586,8 @@ func (factory *Factory_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe factory.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": factory.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -708,6 +759,18 @@ func (factory *Factory_Spec) AssignProperties_From_Factory_Spec(source *storage. // Location factory.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FactoryOperatorSpec + err := operatorSpec.AssignProperties_From_FactoryOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FactoryOperatorSpec() to populate field OperatorSpec") + } + factory.OperatorSpec = &operatorSpec + } else { + factory.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -822,6 +885,18 @@ func (factory *Factory_Spec) AssignProperties_To_Factory_Spec(destination *stora // Location destination.Location = genruntime.ClonePointerToString(factory.Location) + // OperatorSpec + if factory.OperatorSpec != nil { + var operatorSpec storage.FactoryOperatorSpec + err := factory.OperatorSpec.AssignProperties_To_FactoryOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FactoryOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = factory.OriginalVersion() @@ -2152,6 +2227,110 @@ func (identity *FactoryIdentity_STATUS) AssignProperties_To_FactoryIdentity_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FactoryOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FactoryOperatorSpec populates our FactoryOperatorSpec from the provided source FactoryOperatorSpec +func (operator *FactoryOperatorSpec) AssignProperties_From_FactoryOperatorSpec(source *storage.FactoryOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FactoryOperatorSpec populates the provided destination FactoryOperatorSpec from our FactoryOperatorSpec +func (operator *FactoryOperatorSpec) AssignProperties_To_FactoryOperatorSpec(destination *storage.FactoryOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Disabled","Enabled"} type FactoryProperties_PublicNetworkAccess string diff --git a/v2/api/datafactory/v1api20180601/factory_types_gen_test.go b/v2/api/datafactory/v1api20180601/factory_types_gen_test.go index 4c3900166dc..de3cacc60bc 100644 --- a/v2/api/datafactory/v1api20180601/factory_types_gen_test.go +++ b/v2/api/datafactory/v1api20180601/factory_types_gen_test.go @@ -1073,6 +1073,103 @@ func AddIndependentPropertyGeneratorsForFactoryIdentity_STATUS(gens map[string]g gens["Type"] = gen.PtrOf(gen.OneConstOf(FactoryIdentity_Type_STATUS_SystemAssigned, FactoryIdentity_Type_STATUS_SystemAssignedUserAssigned, FactoryIdentity_Type_STATUS_UserAssigned)) } +func Test_FactoryOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FactoryOperatorSpec to FactoryOperatorSpec via AssignProperties_To_FactoryOperatorSpec & AssignProperties_From_FactoryOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFactoryOperatorSpec, FactoryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFactoryOperatorSpec tests if a specific instance of FactoryOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFactoryOperatorSpec(subject FactoryOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FactoryOperatorSpec + err := copied.AssignProperties_To_FactoryOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FactoryOperatorSpec + err = actual.AssignProperties_From_FactoryOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FactoryOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FactoryOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFactoryOperatorSpec, FactoryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFactoryOperatorSpec runs a test to see if a specific instance of FactoryOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFactoryOperatorSpec(subject FactoryOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FactoryOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FactoryOperatorSpec instances for property testing - lazily instantiated by +// FactoryOperatorSpecGenerator() +var factoryOperatorSpecGenerator gopter.Gen + +// FactoryOperatorSpecGenerator returns a generator of FactoryOperatorSpec instances for property testing. +func FactoryOperatorSpecGenerator() gopter.Gen { + if factoryOperatorSpecGenerator != nil { + return factoryOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + factoryOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FactoryOperatorSpec{}), generators) + + return factoryOperatorSpecGenerator +} + func Test_FactoryRepoConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1779,6 +1876,7 @@ func AddRelatedPropertyGeneratorsForFactory_Spec(gens map[string]gopter.Gen) { gen.AlphaString(), GlobalParameterSpecificationGenerator()) gens["Identity"] = gen.PtrOf(FactoryIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FactoryOperatorSpecGenerator()) gens["PurviewConfiguration"] = gen.PtrOf(PurviewConfigurationGenerator()) gens["RepoConfiguration"] = gen.PtrOf(FactoryRepoConfigurationGenerator()) } diff --git a/v2/api/datafactory/v1api20180601/storage/factory_types_gen.go b/v2/api/datafactory/v1api20180601/storage/factory_types_gen.go index e394104d6af..c1fa131a354 100644 --- a/v2/api/datafactory/v1api20180601/storage/factory_types_gen.go +++ b/v2/api/datafactory/v1api20180601/storage/factory_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (factory *Factory) SetConditions(conditions conditions.Conditions) { factory.Status.Conditions = conditions } +var _ configmaps.Exporter = &Factory{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (factory *Factory) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if factory.Spec.OperatorSpec == nil { + return nil + } + return factory.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Factory{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (factory *Factory) SecretDestinationExpressions() []*core.DestinationExpression { + if factory.Spec.OperatorSpec == nil { + return nil + } + return factory.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Factory{} // AzureName returns the Azure name of the resource @@ -156,6 +179,7 @@ type Factory_Spec struct { GlobalParameters map[string]GlobalParameterSpecification `json:"globalParameters,omitempty"` Identity *FactoryIdentity `json:"identity,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *FactoryOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -271,6 +295,14 @@ type FactoryIdentity_STATUS struct { UserAssignedIdentities map[string]v1.JSON `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20180601.FactoryOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FactoryOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20180601.FactoryRepoConfiguration type FactoryRepoConfiguration struct { FactoryGitHub *FactoryGitHubConfiguration `json:"factoryGitHubConfiguration,omitempty"` diff --git a/v2/api/datafactory/v1api20180601/storage/factory_types_gen_test.go b/v2/api/datafactory/v1api20180601/storage/factory_types_gen_test.go index bed75008e26..4572fe88b2e 100644 --- a/v2/api/datafactory/v1api20180601/storage/factory_types_gen_test.go +++ b/v2/api/datafactory/v1api20180601/storage/factory_types_gen_test.go @@ -651,6 +651,61 @@ func AddIndependentPropertyGeneratorsForFactoryIdentity_STATUS(gens map[string]g gens["Type"] = gen.PtrOf(gen.AlphaString()) } +func Test_FactoryOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FactoryOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFactoryOperatorSpec, FactoryOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFactoryOperatorSpec runs a test to see if a specific instance of FactoryOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFactoryOperatorSpec(subject FactoryOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FactoryOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FactoryOperatorSpec instances for property testing - lazily instantiated by +// FactoryOperatorSpecGenerator() +var factoryOperatorSpecGenerator gopter.Gen + +// FactoryOperatorSpecGenerator returns a generator of FactoryOperatorSpec instances for property testing. +func FactoryOperatorSpecGenerator() gopter.Gen { + if factoryOperatorSpecGenerator != nil { + return factoryOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + factoryOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FactoryOperatorSpec{}), generators) + + return factoryOperatorSpecGenerator +} + func Test_FactoryRepoConfiguration_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1106,6 +1161,7 @@ func AddRelatedPropertyGeneratorsForFactory_Spec(gens map[string]gopter.Gen) { gen.AlphaString(), GlobalParameterSpecificationGenerator()) gens["Identity"] = gen.PtrOf(FactoryIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FactoryOperatorSpecGenerator()) gens["PurviewConfiguration"] = gen.PtrOf(PurviewConfigurationGenerator()) gens["RepoConfiguration"] = gen.PtrOf(FactoryRepoConfigurationGenerator()) } diff --git a/v2/api/datafactory/v1api20180601/storage/structure.txt b/v2/api/datafactory/v1api20180601/storage/structure.txt index 7e7c2773e6b..54b90cc069c 100644 --- a/v2/api/datafactory/v1api20180601/storage/structure.txt +++ b/v2/api/datafactory/v1api20180601/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-06-01" Factory: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AdditionalProperties: map[string]v1.JSON │ ├── AzureName: string │ ├── Encryption: *Object (5 properties) @@ -27,6 +27,10 @@ Factory: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/datafactory/v1api20180601/storage/zz_generated.deepcopy.go b/v2/api/datafactory/v1api20180601/storage/zz_generated.deepcopy.go index 56cac730c6e..e5c069198eb 100644 --- a/v2/api/datafactory/v1api20180601/storage/zz_generated.deepcopy.go +++ b/v2/api/datafactory/v1api20180601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -435,6 +436,50 @@ func (in *FactoryList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FactoryOperatorSpec) DeepCopyInto(out *FactoryOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FactoryOperatorSpec. +func (in *FactoryOperatorSpec) DeepCopy() *FactoryOperatorSpec { + if in == nil { + return nil + } + out := new(FactoryOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FactoryRepoConfiguration) DeepCopyInto(out *FactoryRepoConfiguration) { *out = *in @@ -780,6 +825,11 @@ func (in *Factory_Spec) DeepCopyInto(out *Factory_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FactoryOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/datafactory/v1api20180601/structure.txt b/v2/api/datafactory/v1api20180601/structure.txt index ba332a0a184..16dfb05461a 100644 --- a/v2/api/datafactory/v1api20180601/structure.txt +++ b/v2/api/datafactory/v1api20180601/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-06-01" Factory: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AdditionalProperties: map[string]v1.JSON │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 63 @@ -34,6 +34,9 @@ Factory: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" diff --git a/v2/api/datafactory/v1api20180601/zz_generated.deepcopy.go b/v2/api/datafactory/v1api20180601/zz_generated.deepcopy.go index bbfbb2b3e0b..679d27a213a 100644 --- a/v2/api/datafactory/v1api20180601/zz_generated.deepcopy.go +++ b/v2/api/datafactory/v1api20180601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -377,6 +378,43 @@ func (in *FactoryList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FactoryOperatorSpec) DeepCopyInto(out *FactoryOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FactoryOperatorSpec. +func (in *FactoryOperatorSpec) DeepCopy() *FactoryOperatorSpec { + if in == nil { + return nil + } + out := new(FactoryOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FactoryRepoConfiguration) DeepCopyInto(out *FactoryRepoConfiguration) { *out = *in @@ -687,6 +725,11 @@ func (in *Factory_Spec) DeepCopyInto(out *Factory_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FactoryOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dataprotection/v1api20230101/backup_vault_types_gen.go b/v2/api/dataprotection/v1api20230101/backup_vault_types_gen.go index 376e0ee3bc8..78ce66edb20 100644 --- a/v2/api/dataprotection/v1api20230101/backup_vault_types_gen.go +++ b/v2/api/dataprotection/v1api20230101/backup_vault_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -110,6 +112,26 @@ func (vault *BackupVault) defaultAzureName() { // defaultImpl applies the code generated defaults to the BackupVault resource func (vault *BackupVault) defaultImpl() { vault.defaultAzureName() } +var _ configmaps.Exporter = &BackupVault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *BackupVault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *BackupVault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &BackupVault{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -236,7 +258,7 @@ func (vault *BackupVault) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (vault *BackupVault) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateConfigMapDestinations} + return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateSecretDestinations, vault.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -254,6 +276,9 @@ func (vault *BackupVault) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return vault.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return vault.validateConfigMapDestinations() }, @@ -265,13 +290,13 @@ func (vault *BackupVault) validateConfigMapDestinations() (admission.Warnings, e if vault.Spec.OperatorSpec == nil { return nil, nil } - if vault.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - vault.Spec.OperatorSpec.ConfigMaps.PrincipalId, + var toValidate []*genruntime.ConfigMapDestination + if vault.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + vault.Spec.OperatorSpec.ConfigMaps.PrincipalId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(vault, toValidate, vault.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -288,6 +313,14 @@ func (vault *BackupVault) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (vault *BackupVault) validateSecretDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (vault *BackupVault) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BackupVault) @@ -1343,13 +1376,37 @@ func (vault *BackupVault_STATUS) AssignProperties_To_BackupVault_STATUS(destinat // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type BackupVaultOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_BackupVaultOperatorSpec populates our BackupVaultOperatorSpec from the provided source BackupVaultOperatorSpec func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperatorSpec(source *storage.BackupVaultOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap BackupVaultOperatorConfigMaps @@ -1362,6 +1419,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperat operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -1371,6 +1446,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.BackupVaultOperatorConfigMaps @@ -1383,6 +1476,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen.go b/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen.go index 21d4caea54d..7859bcef448 100644 --- a/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen.go +++ b/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (policy *BackupVaultsBackupPolicy) defaultAzureName() { // defaultImpl applies the code generated defaults to the BackupVaultsBackupPolicy resource func (policy *BackupVaultsBackupPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &BackupVaultsBackupPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *BackupVaultsBackupPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *BackupVaultsBackupPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BackupVaultsBackupPolicy{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (policy *BackupVaultsBackupPolicy) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (policy *BackupVaultsBackupPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (policy *BackupVaultsBackupPolicy) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *BackupVaultsBackupPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (policy *BackupVaultsBackupPolicy) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *BackupVaultsBackupPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *BackupVaultsBackupPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BackupVaultsBackupPolicy) @@ -333,6 +378,10 @@ type BackupVaultsBackupPolicy_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BackupVaultsBackupPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -382,6 +431,8 @@ func (policy *BackupVaultsBackupPolicy_Spec) PopulateFromARM(owner genruntime.Ar // Set property "AzureName": policy.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -459,6 +510,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_From_BackupVaultsB // AzureName policy.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackupVaultsBackupPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -491,6 +554,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_To_BackupVaultsBac // AzureName destination.AzureName = policy.AzureName + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.BackupVaultsBackupPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -760,6 +835,110 @@ func (policy *BackupVaultsBackupPolicy_STATUS) AssignProperties_To_BackupVaultsB return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec populates our BackupVaultsBackupPolicyOperatorSpec from the provided source BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source *storage.BackupVaultsBackupPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec populates the provided destination BackupVaultsBackupPolicyOperatorSpec from our BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(destination *storage.BackupVaultsBackupPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type BaseBackupPolicy struct { // BackupPolicy: Mutually exclusive with all other properties BackupPolicy *BackupPolicy `json:"backupPolicy,omitempty"` diff --git a/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen_test.go b/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen_test.go index 9868fe186d6..31151abbbc2 100644 --- a/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen_test.go +++ b/v2/api/dataprotection/v1api20230101/backup_vaults_backup_policy_types_gen_test.go @@ -2381,6 +2381,103 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy(gens map[string]gop gens["Status"] = BackupVaultsBackupPolicy_STATUSGenerator() } +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackupVaultsBackupPolicyOperatorSpec to BackupVaultsBackupPolicyOperatorSpec via AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec & AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec tests if a specific instance of BackupVaultsBackupPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230101s.BackupVaultsBackupPolicyOperatorSpec + err := copied.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackupVaultsBackupPolicyOperatorSpec + err = actual.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupPolicyOperatorSpecGenerator() +var backupVaultsBackupPolicyOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupPolicyOperatorSpecGenerator returns a generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing. +func BackupVaultsBackupPolicyOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupPolicyOperatorSpecGenerator != nil { + return backupVaultsBackupPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupPolicyOperatorSpec{}), generators) + + return backupVaultsBackupPolicyOperatorSpecGenerator +} + func Test_BackupVaultsBackupPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2615,6 +2712,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[s // AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupPolicyOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BaseBackupPolicyGenerator()) } diff --git a/v2/api/dataprotection/v1api20230101/storage/backup_vault_types_gen.go b/v2/api/dataprotection/v1api20230101/storage/backup_vault_types_gen.go index 75566e41229..80e5f67a0ff 100644 --- a/v2/api/dataprotection/v1api20230101/storage/backup_vault_types_gen.go +++ b/v2/api/dataprotection/v1api20230101/storage/backup_vault_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -70,6 +72,26 @@ func (vault *BackupVault) ConvertTo(hub conversion.Hub) error { return vault.AssignProperties_To_BackupVault(destination) } +var _ configmaps.Exporter = &BackupVault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *BackupVault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *BackupVault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &BackupVault{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -1000,8 +1022,10 @@ func (vault *BackupVault_STATUS) AssignProperties_To_BackupVault_STATUS(destinat // Storage version of v1api20230101.BackupVaultOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type BackupVaultOperatorSpec struct { - ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_BackupVaultOperatorSpec populates our BackupVaultOperatorSpec from the provided source BackupVaultOperatorSpec @@ -1009,6 +1033,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperat // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap BackupVaultOperatorConfigMaps @@ -1021,6 +1063,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperat operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { operator.PropertyBag = propertyBag @@ -1046,6 +1106,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.BackupVaultOperatorConfigMaps @@ -1058,6 +1136,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen.go b/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen.go index 214489ff76d..ee5419de93e 100644 --- a/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen.go +++ b/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dataprotection/v1api20231101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (policy *BackupVaultsBackupPolicy) ConvertTo(hub conversion.Hub) error { return policy.AssignProperties_To_BackupVaultsBackupPolicy(destination) } +var _ configmaps.Exporter = &BackupVaultsBackupPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *BackupVaultsBackupPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *BackupVaultsBackupPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BackupVaultsBackupPolicy{} // AzureName returns the Azure name of the resource @@ -235,8 +258,9 @@ type augmentConversionForBackupVaultsBackupPolicy interface { type BackupVaultsBackupPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *BackupVaultsBackupPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -305,6 +329,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_From_BackupVaultsB // AzureName policy.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackupVaultsBackupPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -356,6 +392,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_To_BackupVaultsBac // AzureName destination.AzureName = policy.AzureName + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.BackupVaultsBackupPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -592,6 +640,136 @@ type augmentConversionForBackupVaultsBackupPolicy_STATUS interface { AssignPropertiesTo(dst *storage.BackupVaultsBackupPolicy_STATUS) error } +// Storage version of v1api20230101.BackupVaultsBackupPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec populates our BackupVaultsBackupPolicyOperatorSpec from the provided source BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source *storage.BackupVaultsBackupPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForBackupVaultsBackupPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForBackupVaultsBackupPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec populates the provided destination BackupVaultsBackupPolicyOperatorSpec from our BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(destination *storage.BackupVaultsBackupPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForBackupVaultsBackupPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForBackupVaultsBackupPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20230101.BaseBackupPolicy type BaseBackupPolicy struct { BackupPolicy *BackupPolicy `json:"backupPolicy,omitempty"` @@ -752,6 +930,11 @@ func (policy *BaseBackupPolicy_STATUS) AssignProperties_To_BaseBackupPolicy_STAT return nil } +type augmentConversionForBackupVaultsBackupPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.BackupVaultsBackupPolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.BackupVaultsBackupPolicyOperatorSpec) error +} + type augmentConversionForBaseBackupPolicy interface { AssignPropertiesFrom(src *storage.BaseBackupPolicy) error AssignPropertiesTo(dst *storage.BaseBackupPolicy) error diff --git a/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen_test.go b/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen_test.go index 85e5c2b4e02..6f89c0612fe 100644 --- a/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen_test.go +++ b/v2/api/dataprotection/v1api20230101/storage/backup_vaults_backup_policy_types_gen_test.go @@ -2380,6 +2380,103 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy(gens map[string]gop gens["Status"] = BackupVaultsBackupPolicy_STATUSGenerator() } +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackupVaultsBackupPolicyOperatorSpec to BackupVaultsBackupPolicyOperatorSpec via AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec & AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec tests if a specific instance of BackupVaultsBackupPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BackupVaultsBackupPolicyOperatorSpec + err := copied.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackupVaultsBackupPolicyOperatorSpec + err = actual.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupPolicyOperatorSpecGenerator() +var backupVaultsBackupPolicyOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupPolicyOperatorSpecGenerator returns a generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing. +func BackupVaultsBackupPolicyOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupPolicyOperatorSpecGenerator != nil { + return backupVaultsBackupPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupPolicyOperatorSpec{}), generators) + + return backupVaultsBackupPolicyOperatorSpecGenerator +} + func Test_BackupVaultsBackupPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2615,6 +2712,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[s // AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupPolicyOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BaseBackupPolicyGenerator()) } diff --git a/v2/api/dataprotection/v1api20230101/storage/structure.txt b/v2/api/dataprotection/v1api20230101/storage/structure.txt index 6850e130a39..72368546986 100644 --- a/v2/api/dataprotection/v1api20230101/storage/structure.txt +++ b/v2/api/dataprotection/v1api20230101/storage/structure.txt @@ -11,11 +11,13 @@ BackupVault: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Type: *string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (5 properties) @@ -104,8 +106,12 @@ BackupVault: Resource └── Type: *string BackupVaultsBackupPolicy: Resource ├── Owner: dataprotection/v1api20230101.BackupVault -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (2 properties) @@ -347,6 +353,7 @@ augmentConversionForBackupVaultSpec: Interface augmentConversionForBackupVault_STATUS: Interface augmentConversionForBackupVault_Spec: Interface augmentConversionForBackupVaultsBackupPolicy: Interface +augmentConversionForBackupVaultsBackupPolicyOperatorSpec: Interface augmentConversionForBackupVaultsBackupPolicy_STATUS: Interface augmentConversionForBackupVaultsBackupPolicy_Spec: Interface augmentConversionForBaseBackupPolicy: Interface diff --git a/v2/api/dataprotection/v1api20230101/storage/zz_generated.deepcopy.go b/v2/api/dataprotection/v1api20230101/storage/zz_generated.deepcopy.go index d3797dc97d3..ba0ace69197 100644 --- a/v2/api/dataprotection/v1api20230101/storage/zz_generated.deepcopy.go +++ b/v2/api/dataprotection/v1api20230101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -836,6 +837,17 @@ func (in *BackupVaultOperatorConfigMaps) DeepCopy() *BackupVaultOperatorConfigMa // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(BackupVaultOperatorConfigMaps) @@ -848,6 +860,17 @@ func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultOperatorSpec. @@ -1157,6 +1180,50 @@ func (in *BackupVaultsBackupPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopyInto(out *BackupVaultsBackupPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupPolicyOperatorSpec. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopy() *BackupVaultsBackupPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_STATUS) DeepCopyInto(out *BackupVaultsBackupPolicy_STATUS) { *out = *in @@ -1214,6 +1281,11 @@ func (in *BackupVaultsBackupPolicy_STATUS) DeepCopy() *BackupVaultsBackupPolicy_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_Spec) DeepCopyInto(out *BackupVaultsBackupPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dataprotection/v1api20230101/structure.txt b/v2/api/dataprotection/v1api20230101/structure.txt index 119a0736c09..604dac6f94d 100644 --- a/v2/api/dataprotection/v1api20230101/structure.txt +++ b/v2/api/dataprotection/v1api20230101/structure.txt @@ -10,9 +10,11 @@ BackupVault: Resource │ ├── Identity: *Object (1 property) │ │ └── Type: *string │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (4 properties) │ │ ├── FeatureSettings: *Object (1 property) @@ -134,8 +136,11 @@ BackupVault: Resource └── Type: *string BackupVaultsBackupPolicy: Resource ├── Owner: BackupVault -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Properties: *Object (1 property) │ └── BackupPolicy: *Object (3 properties) diff --git a/v2/api/dataprotection/v1api20230101/zz_generated.deepcopy.go b/v2/api/dataprotection/v1api20230101/zz_generated.deepcopy.go index bff20fe81c5..5ebec039b6f 100644 --- a/v2/api/dataprotection/v1api20230101/zz_generated.deepcopy.go +++ b/v2/api/dataprotection/v1api20230101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -675,11 +676,33 @@ func (in *BackupVaultOperatorConfigMaps) DeepCopy() *BackupVaultOperatorConfigMa // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(BackupVaultOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultOperatorSpec. @@ -961,6 +984,43 @@ func (in *BackupVaultsBackupPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopyInto(out *BackupVaultsBackupPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupPolicyOperatorSpec. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopy() *BackupVaultsBackupPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_STATUS) DeepCopyInto(out *BackupVaultsBackupPolicy_STATUS) { *out = *in @@ -1011,6 +1071,11 @@ func (in *BackupVaultsBackupPolicy_STATUS) DeepCopy() *BackupVaultsBackupPolicy_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_Spec) DeepCopyInto(out *BackupVaultsBackupPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dataprotection/v1api20231101/backup_vault_types_gen.go b/v2/api/dataprotection/v1api20231101/backup_vault_types_gen.go index fff1c782dd6..2b9ef6d1470 100644 --- a/v2/api/dataprotection/v1api20231101/backup_vault_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/backup_vault_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (vault *BackupVault) defaultAzureName() { // defaultImpl applies the code generated defaults to the BackupVault resource func (vault *BackupVault) defaultImpl() { vault.defaultAzureName() } +var _ configmaps.Exporter = &BackupVault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *BackupVault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *BackupVault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &BackupVault{} // InitializeSpec initializes the spec for this resource from the given status @@ -233,7 +255,7 @@ func (vault *BackupVault) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (vault *BackupVault) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateConfigMapDestinations} + return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateSecretDestinations, vault.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -251,6 +273,9 @@ func (vault *BackupVault) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return vault.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return vault.validateConfigMapDestinations() }, @@ -262,13 +287,13 @@ func (vault *BackupVault) validateConfigMapDestinations() (admission.Warnings, e if vault.Spec.OperatorSpec == nil { return nil, nil } - if vault.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - vault.Spec.OperatorSpec.ConfigMaps.PrincipalId, + var toValidate []*genruntime.ConfigMapDestination + if vault.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + vault.Spec.OperatorSpec.ConfigMaps.PrincipalId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(vault, toValidate, vault.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -285,6 +310,14 @@ func (vault *BackupVault) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (vault *BackupVault) validateSecretDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (vault *BackupVault) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BackupVault) @@ -1419,13 +1452,37 @@ func (vault *BackupVault_STATUS) AssignProperties_To_BackupVault_STATUS(destinat // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type BackupVaultOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_BackupVaultOperatorSpec populates our BackupVaultOperatorSpec from the provided source BackupVaultOperatorSpec func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperatorSpec(source *storage.BackupVaultOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap BackupVaultOperatorConfigMaps @@ -1438,6 +1495,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_From_BackupVaultOperat operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -1447,6 +1522,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.BackupVaultOperatorConfigMaps @@ -1459,6 +1552,24 @@ func (operator *BackupVaultOperatorSpec) AssignProperties_To_BackupVaultOperator destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen.go b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen.go index 9fb516b0bc0..f0034a1de50 100644 --- a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (instance *BackupVaultsBackupInstance) defaultAzureName() { // defaultImpl applies the code generated defaults to the BackupVaultsBackupInstance resource func (instance *BackupVaultsBackupInstance) defaultImpl() { instance.defaultAzureName() } +var _ configmaps.Exporter = &BackupVaultsBackupInstance{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (instance *BackupVaultsBackupInstance) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if instance.Spec.OperatorSpec == nil { + return nil + } + return instance.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupInstance{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (instance *BackupVaultsBackupInstance) SecretDestinationExpressions() []*core.DestinationExpression { + if instance.Spec.OperatorSpec == nil { + return nil + } + return instance.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &BackupVaultsBackupInstance{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (instance *BackupVaultsBackupInstance) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (instance *BackupVaultsBackupInstance) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){instance.validateResourceReferences, instance.validateOwnerReference} + return []func() (admission.Warnings, error){instance.validateResourceReferences, instance.validateOwnerReference, instance.validateSecretDestinations, instance.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (instance *BackupVaultsBackupInstance) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return instance.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return instance.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return instance.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (instance *BackupVaultsBackupInstance) validateConfigMapDestinations() (admission.Warnings, error) { + if instance.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(instance, nil, instance.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (instance *BackupVaultsBackupInstance) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (instance *BackupVaultsBackupInstance) validateSecretDestinations() (admission.Warnings, error) { + if instance.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(instance, nil, instance.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (instance *BackupVaultsBackupInstance) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BackupVaultsBackupInstance) @@ -330,6 +375,10 @@ type BackupVaultsBackupInstance_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BackupVaultsBackupInstanceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -390,6 +439,8 @@ func (instance *BackupVaultsBackupInstance_Spec) PopulateFromARM(owner genruntim // Set property "AzureName": instance.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": instance.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -475,6 +526,18 @@ func (instance *BackupVaultsBackupInstance_Spec) AssignProperties_From_BackupVau // AzureName instance.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackupVaultsBackupInstanceOperatorSpec + err := operatorSpec.AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec() to populate field OperatorSpec") + } + instance.OperatorSpec = &operatorSpec + } else { + instance.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -510,6 +573,18 @@ func (instance *BackupVaultsBackupInstance_Spec) AssignProperties_To_BackupVault // AzureName destination.AzureName = instance.AzureName + // OperatorSpec + if instance.OperatorSpec != nil { + var operatorSpec storage.BackupVaultsBackupInstanceOperatorSpec + err := instance.OperatorSpec.AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = instance.OriginalVersion() @@ -1688,6 +1763,110 @@ func (instance *BackupInstance_STATUS) AssignProperties_To_BackupInstance_STATUS return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupInstanceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec populates our BackupVaultsBackupInstanceOperatorSpec from the provided source BackupVaultsBackupInstanceOperatorSpec +func (operator *BackupVaultsBackupInstanceOperatorSpec) AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec(source *storage.BackupVaultsBackupInstanceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec populates the provided destination BackupVaultsBackupInstanceOperatorSpec from our BackupVaultsBackupInstanceOperatorSpec +func (operator *BackupVaultsBackupInstanceOperatorSpec) AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec(destination *storage.BackupVaultsBackupInstanceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AuthCredentials struct { // SecretStoreBasedAuthCredentials: Mutually exclusive with all other properties SecretStoreBasedAuthCredentials *SecretStoreBasedAuthCredentials `json:"secretStoreBasedAuthCredentials,omitempty"` diff --git a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen_test.go b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen_test.go index e66145a98ef..e2681abefa5 100644 --- a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen_test.go +++ b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_instance_types_gen_test.go @@ -1084,6 +1084,103 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance(gens map[string]g gens["Status"] = BackupVaultsBackupInstance_STATUSGenerator() } +func Test_BackupVaultsBackupInstanceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackupVaultsBackupInstanceOperatorSpec to BackupVaultsBackupInstanceOperatorSpec via AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec & AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackupVaultsBackupInstanceOperatorSpec, BackupVaultsBackupInstanceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackupVaultsBackupInstanceOperatorSpec tests if a specific instance of BackupVaultsBackupInstanceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackupVaultsBackupInstanceOperatorSpec(subject BackupVaultsBackupInstanceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BackupVaultsBackupInstanceOperatorSpec + err := copied.AssignProperties_To_BackupVaultsBackupInstanceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackupVaultsBackupInstanceOperatorSpec + err = actual.AssignProperties_From_BackupVaultsBackupInstanceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackupVaultsBackupInstanceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupInstanceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec, BackupVaultsBackupInstanceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupInstanceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec(subject BackupVaultsBackupInstanceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupInstanceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupInstanceOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupInstanceOperatorSpecGenerator() +var backupVaultsBackupInstanceOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupInstanceOperatorSpecGenerator returns a generator of BackupVaultsBackupInstanceOperatorSpec instances for property testing. +func BackupVaultsBackupInstanceOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupInstanceOperatorSpecGenerator != nil { + return backupVaultsBackupInstanceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupInstanceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupInstanceOperatorSpec{}), generators) + + return backupVaultsBackupInstanceOperatorSpecGenerator +} + func Test_BackupVaultsBackupInstance_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1324,6 +1421,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupInstance_Spec(gens map // AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupInstanceOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BackupInstanceGenerator()) } diff --git a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen.go b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen.go index ea1b3b84bdf..956eff0c0b3 100644 --- a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (policy *BackupVaultsBackupPolicy) defaultAzureName() { // defaultImpl applies the code generated defaults to the BackupVaultsBackupPolicy resource func (policy *BackupVaultsBackupPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &BackupVaultsBackupPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *BackupVaultsBackupPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *BackupVaultsBackupPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &BackupVaultsBackupPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (policy *BackupVaultsBackupPolicy) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (policy *BackupVaultsBackupPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (policy *BackupVaultsBackupPolicy) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *BackupVaultsBackupPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (policy *BackupVaultsBackupPolicy) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *BackupVaultsBackupPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *BackupVaultsBackupPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BackupVaultsBackupPolicy) @@ -330,6 +375,10 @@ type BackupVaultsBackupPolicy_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BackupVaultsBackupPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -379,6 +428,8 @@ func (policy *BackupVaultsBackupPolicy_Spec) PopulateFromARM(owner genruntime.Ar // Set property "AzureName": policy.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -456,6 +507,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_From_BackupVaultsB // AzureName policy.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BackupVaultsBackupPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -488,6 +551,18 @@ func (policy *BackupVaultsBackupPolicy_Spec) AssignProperties_To_BackupVaultsBac // AzureName destination.AzureName = policy.AzureName + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.BackupVaultsBackupPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -776,6 +851,110 @@ func (policy *BackupVaultsBackupPolicy_STATUS) AssignProperties_To_BackupVaultsB return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec populates our BackupVaultsBackupPolicyOperatorSpec from the provided source BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(source *storage.BackupVaultsBackupPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec populates the provided destination BackupVaultsBackupPolicyOperatorSpec from our BackupVaultsBackupPolicyOperatorSpec +func (operator *BackupVaultsBackupPolicyOperatorSpec) AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(destination *storage.BackupVaultsBackupPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type BaseBackupPolicy struct { // BackupPolicy: Mutually exclusive with all other properties BackupPolicy *BackupPolicy `json:"backupPolicy,omitempty"` diff --git a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen_test.go b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen_test.go index 9a18bcb797b..542248a8b06 100644 --- a/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen_test.go +++ b/v2/api/dataprotection/v1api20231101/backup_vaults_backup_policy_types_gen_test.go @@ -2380,6 +2380,103 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy(gens map[string]gop gens["Status"] = BackupVaultsBackupPolicy_STATUSGenerator() } +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BackupVaultsBackupPolicyOperatorSpec to BackupVaultsBackupPolicyOperatorSpec via AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec & AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec tests if a specific instance of BackupVaultsBackupPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BackupVaultsBackupPolicyOperatorSpec + err := copied.AssignProperties_To_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BackupVaultsBackupPolicyOperatorSpec + err = actual.AssignProperties_From_BackupVaultsBackupPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupPolicyOperatorSpecGenerator() +var backupVaultsBackupPolicyOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupPolicyOperatorSpecGenerator returns a generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing. +func BackupVaultsBackupPolicyOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupPolicyOperatorSpecGenerator != nil { + return backupVaultsBackupPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupPolicyOperatorSpec{}), generators) + + return backupVaultsBackupPolicyOperatorSpecGenerator +} + func Test_BackupVaultsBackupPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2614,6 +2711,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[s // AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupPolicyOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BaseBackupPolicyGenerator()) } diff --git a/v2/api/dataprotection/v1api20231101/storage/backup_vault_types_gen.go b/v2/api/dataprotection/v1api20231101/storage/backup_vault_types_gen.go index 742b2b8a8c5..36b6f0ef153 100644 --- a/v2/api/dataprotection/v1api20231101/storage/backup_vault_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/storage/backup_vault_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (vault *BackupVault) SetConditions(conditions conditions.Conditions) { vault.Status.Conditions = conditions } +var _ configmaps.Exporter = &BackupVault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *BackupVault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *BackupVault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &BackupVault{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -263,8 +285,10 @@ type BackupVault_STATUS struct { // Storage version of v1api20231101.BackupVaultOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type BackupVaultOperatorSpec struct { - ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *BackupVaultOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20231101.BackupVaultSpec diff --git a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen.go b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen.go index 9d882cdb319..8daefecda8f 100644 --- a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (instance *BackupVaultsBackupInstance) SetConditions(conditions conditions. instance.Status.Conditions = conditions } +var _ configmaps.Exporter = &BackupVaultsBackupInstance{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (instance *BackupVaultsBackupInstance) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if instance.Spec.OperatorSpec == nil { + return nil + } + return instance.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupInstance{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (instance *BackupVaultsBackupInstance) SecretDestinationExpressions() []*core.DestinationExpression { + if instance.Spec.OperatorSpec == nil { + return nil + } + return instance.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BackupVaultsBackupInstance{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type BackupVaultsBackupInstanceList struct { type BackupVaultsBackupInstance_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *BackupVaultsBackupInstanceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -239,6 +263,14 @@ type BackupInstance_STATUS struct { ValidationType *string `json:"validationType,omitempty"` } +// Storage version of v1api20231101.BackupVaultsBackupInstanceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupInstanceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231101.AuthCredentials type AuthCredentials struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` diff --git a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen_test.go b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen_test.go index b865cef5d11..74e991900df 100644 --- a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen_test.go +++ b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_instance_types_gen_test.go @@ -650,6 +650,61 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance(gens map[string]g gens["Status"] = BackupVaultsBackupInstance_STATUSGenerator() } +func Test_BackupVaultsBackupInstanceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupInstanceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec, BackupVaultsBackupInstanceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupInstanceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupInstanceOperatorSpec(subject BackupVaultsBackupInstanceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupInstanceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupInstanceOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupInstanceOperatorSpecGenerator() +var backupVaultsBackupInstanceOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupInstanceOperatorSpecGenerator returns a generator of BackupVaultsBackupInstanceOperatorSpec instances for property testing. +func BackupVaultsBackupInstanceOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupInstanceOperatorSpecGenerator != nil { + return backupVaultsBackupInstanceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupInstanceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupInstanceOperatorSpec{}), generators) + + return backupVaultsBackupInstanceOperatorSpecGenerator +} + func Test_BackupVaultsBackupInstance_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -807,6 +862,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupInstance_Spec(gens map // AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupInstance_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupInstanceOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BackupInstanceGenerator()) } diff --git a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen.go b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen.go index 7a066a28c42..b6a2ea9110a 100644 --- a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen.go +++ b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *BackupVaultsBackupPolicy) SetConditions(conditions conditions.Cond policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &BackupVaultsBackupPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *BackupVaultsBackupPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BackupVaultsBackupPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *BackupVaultsBackupPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BackupVaultsBackupPolicy{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type BackupVaultsBackupPolicyList struct { type BackupVaultsBackupPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *BackupVaultsBackupPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -205,6 +229,14 @@ func (policy *BackupVaultsBackupPolicy_STATUS) ConvertStatusTo(destination genru return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20231101.BackupVaultsBackupPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BackupVaultsBackupPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231101.BaseBackupPolicy type BaseBackupPolicy struct { BackupPolicy *BackupPolicy `json:"backupPolicy,omitempty"` diff --git a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen_test.go b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen_test.go index a458ab28174..53d28276536 100644 --- a/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen_test.go +++ b/v2/api/dataprotection/v1api20231101/storage/backup_vaults_backup_policy_types_gen_test.go @@ -1454,6 +1454,61 @@ func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy(gens map[string]gop gens["Status"] = BackupVaultsBackupPolicy_STATUSGenerator() } +func Test_BackupVaultsBackupPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BackupVaultsBackupPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec, BackupVaultsBackupPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec runs a test to see if a specific instance of BackupVaultsBackupPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBackupVaultsBackupPolicyOperatorSpec(subject BackupVaultsBackupPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BackupVaultsBackupPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing - lazily instantiated by +// BackupVaultsBackupPolicyOperatorSpecGenerator() +var backupVaultsBackupPolicyOperatorSpecGenerator gopter.Gen + +// BackupVaultsBackupPolicyOperatorSpecGenerator returns a generator of BackupVaultsBackupPolicyOperatorSpec instances for property testing. +func BackupVaultsBackupPolicyOperatorSpecGenerator() gopter.Gen { + if backupVaultsBackupPolicyOperatorSpecGenerator != nil { + return backupVaultsBackupPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + backupVaultsBackupPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BackupVaultsBackupPolicyOperatorSpec{}), generators) + + return backupVaultsBackupPolicyOperatorSpecGenerator +} + func Test_BackupVaultsBackupPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1605,6 +1660,7 @@ func AddIndependentPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[s // AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBackupVaultsBackupPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(BackupVaultsBackupPolicyOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(BaseBackupPolicyGenerator()) } diff --git a/v2/api/dataprotection/v1api20231101/storage/structure.txt b/v2/api/dataprotection/v1api20231101/storage/structure.txt index a08482cebcf..c44b5f28c39 100644 --- a/v2/api/dataprotection/v1api20231101/storage/structure.txt +++ b/v2/api/dataprotection/v1api20231101/storage/structure.txt @@ -14,11 +14,13 @@ BackupVault: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (6 properties) @@ -120,8 +122,12 @@ BackupVault: Resource └── Type: *string BackupVaultsBackupInstance: Resource ├── Owner: dataprotection/v1api20231101.BackupVault -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (9 properties) @@ -375,8 +381,12 @@ BackupVaultsBackupInstance: Resource └── Type: *string BackupVaultsBackupPolicy: Resource ├── Owner: dataprotection/v1api20231101.BackupVault -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (2 properties) diff --git a/v2/api/dataprotection/v1api20231101/storage/zz_generated.deepcopy.go b/v2/api/dataprotection/v1api20231101/storage/zz_generated.deepcopy.go index ae2e2e2499c..c03998019f3 100644 --- a/v2/api/dataprotection/v1api20231101/storage/zz_generated.deepcopy.go +++ b/v2/api/dataprotection/v1api20231101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1172,6 +1173,17 @@ func (in *BackupVaultOperatorConfigMaps) DeepCopy() *BackupVaultOperatorConfigMa // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(BackupVaultOperatorConfigMaps) @@ -1184,6 +1196,17 @@ func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultOperatorSpec. @@ -1508,6 +1531,50 @@ func (in *BackupVaultsBackupInstanceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupInstanceOperatorSpec) DeepCopyInto(out *BackupVaultsBackupInstanceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupInstanceOperatorSpec. +func (in *BackupVaultsBackupInstanceOperatorSpec) DeepCopy() *BackupVaultsBackupInstanceOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupInstanceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupInstance_STATUS) DeepCopyInto(out *BackupVaultsBackupInstance_STATUS) { *out = *in @@ -1572,6 +1639,11 @@ func (in *BackupVaultsBackupInstance_STATUS) DeepCopy() *BackupVaultsBackupInsta // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupInstance_Spec) DeepCopyInto(out *BackupVaultsBackupInstance_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupInstanceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1667,6 +1739,50 @@ func (in *BackupVaultsBackupPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopyInto(out *BackupVaultsBackupPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupPolicyOperatorSpec. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopy() *BackupVaultsBackupPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_STATUS) DeepCopyInto(out *BackupVaultsBackupPolicy_STATUS) { *out = *in @@ -1724,6 +1840,11 @@ func (in *BackupVaultsBackupPolicy_STATUS) DeepCopy() *BackupVaultsBackupPolicy_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_Spec) DeepCopyInto(out *BackupVaultsBackupPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dataprotection/v1api20231101/structure.txt b/v2/api/dataprotection/v1api20231101/structure.txt index b1343ab4c0d..6575b7a1815 100644 --- a/v2/api/dataprotection/v1api20231101/structure.txt +++ b/v2/api/dataprotection/v1api20231101/structure.txt @@ -12,9 +12,11 @@ BackupVault: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (5 properties) │ │ ├── FeatureSettings: *Object (2 properties) @@ -155,8 +157,11 @@ BackupVault: Resource └── Type: *string BackupVaultsBackupInstance: Resource ├── Owner: BackupVault -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (8 properties) │ │ ├── DataSourceInfo: *Object (8 properties) @@ -407,8 +412,11 @@ BackupVaultsBackupInstance: Resource └── Type: *string BackupVaultsBackupPolicy: Resource ├── Owner: BackupVault -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Properties: *Object (1 property) │ └── BackupPolicy: *Object (3 properties) diff --git a/v2/api/dataprotection/v1api20231101/zz_generated.deepcopy.go b/v2/api/dataprotection/v1api20231101/zz_generated.deepcopy.go index fa2cab19005..54753866b17 100644 --- a/v2/api/dataprotection/v1api20231101/zz_generated.deepcopy.go +++ b/v2/api/dataprotection/v1api20231101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20231101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -955,11 +956,33 @@ func (in *BackupVaultOperatorConfigMaps) DeepCopy() *BackupVaultOperatorConfigMa // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultOperatorSpec) DeepCopyInto(out *BackupVaultOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(BackupVaultOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultOperatorSpec. @@ -1256,6 +1279,43 @@ func (in *BackupVaultsBackupInstanceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupInstanceOperatorSpec) DeepCopyInto(out *BackupVaultsBackupInstanceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupInstanceOperatorSpec. +func (in *BackupVaultsBackupInstanceOperatorSpec) DeepCopy() *BackupVaultsBackupInstanceOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupInstanceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupInstance_STATUS) DeepCopyInto(out *BackupVaultsBackupInstance_STATUS) { *out = *in @@ -1313,6 +1373,11 @@ func (in *BackupVaultsBackupInstance_STATUS) DeepCopy() *BackupVaultsBackupInsta // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupInstance_Spec) DeepCopyInto(out *BackupVaultsBackupInstance_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupInstanceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1401,6 +1466,43 @@ func (in *BackupVaultsBackupPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopyInto(out *BackupVaultsBackupPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupVaultsBackupPolicyOperatorSpec. +func (in *BackupVaultsBackupPolicyOperatorSpec) DeepCopy() *BackupVaultsBackupPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(BackupVaultsBackupPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_STATUS) DeepCopyInto(out *BackupVaultsBackupPolicy_STATUS) { *out = *in @@ -1451,6 +1553,11 @@ func (in *BackupVaultsBackupPolicy_STATUS) DeepCopy() *BackupVaultsBackupPolicy_ // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BackupVaultsBackupPolicy_Spec) DeepCopyInto(out *BackupVaultsBackupPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BackupVaultsBackupPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformariadb/v1api20180601/configuration_types_gen.go b/v2/api/dbformariadb/v1api20180601/configuration_types_gen.go index 634c5f39f5c..16a35d09a3e 100644 --- a/v2/api/dbformariadb/v1api20180601/configuration_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (configuration *Configuration) defaultAzureName() { // defaultImpl applies the code generated defaults to the Configuration resource func (configuration *Configuration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &Configuration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *Configuration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Configuration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *Configuration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Configuration{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (configuration *Configuration) ValidateUpdate(old runtime.Object) (admissio // createValidations validates the creation of the resource func (configuration *Configuration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -226,9 +249,23 @@ func (configuration *Configuration) updateValidations() []func(old runtime.Objec func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *Configuration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (configuration *Configuration) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(configuration) @@ -243,6 +280,14 @@ func (configuration *Configuration) validateResourceReferences() (admission.Warn return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *Configuration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *Configuration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Configuration) @@ -334,6 +379,10 @@ type Configuration_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -389,6 +438,8 @@ func (configuration *Configuration_Spec) PopulateFromARM(owner genruntime.Arbitr // Set property "AzureName": configuration.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -473,6 +524,18 @@ func (configuration *Configuration_Spec) AssignProperties_From_Configuration_Spe // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_ConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -499,6 +562,18 @@ func (configuration *Configuration_Spec) AssignProperties_To_Configuration_Spec( // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.ConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_ConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -808,6 +883,110 @@ func (configuration *Configuration_STATUS) AssignProperties_To_Configuration_STA return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ConfigurationOperatorSpec populates our ConfigurationOperatorSpec from the provided source ConfigurationOperatorSpec +func (operator *ConfigurationOperatorSpec) AssignProperties_From_ConfigurationOperatorSpec(source *storage.ConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ConfigurationOperatorSpec populates the provided destination ConfigurationOperatorSpec from our ConfigurationOperatorSpec +func (operator *ConfigurationOperatorSpec) AssignProperties_To_ConfigurationOperatorSpec(destination *storage.ConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Configuration{}, &ConfigurationList{}) } diff --git a/v2/api/dbformariadb/v1api20180601/configuration_types_gen_test.go b/v2/api/dbformariadb/v1api20180601/configuration_types_gen_test.go index 271aad0f49c..01ed20c6522 100644 --- a/v2/api/dbformariadb/v1api20180601/configuration_types_gen_test.go +++ b/v2/api/dbformariadb/v1api20180601/configuration_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForConfiguration(gens map[string]gopter.Gen) { gens["Status"] = Configuration_STATUSGenerator() } +func Test_ConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ConfigurationOperatorSpec to ConfigurationOperatorSpec via AssignProperties_To_ConfigurationOperatorSpec & AssignProperties_From_ConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForConfigurationOperatorSpec, ConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForConfigurationOperatorSpec tests if a specific instance of ConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForConfigurationOperatorSpec(subject ConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ConfigurationOperatorSpec + err := copied.AssignProperties_To_ConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ConfigurationOperatorSpec + err = actual.AssignProperties_From_ConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForConfigurationOperatorSpec, ConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForConfigurationOperatorSpec runs a test to see if a specific instance of ConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForConfigurationOperatorSpec(subject ConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ConfigurationOperatorSpec instances for property testing - lazily instantiated by +// ConfigurationOperatorSpecGenerator() +var configurationOperatorSpecGenerator gopter.Gen + +// ConfigurationOperatorSpecGenerator returns a generator of ConfigurationOperatorSpec instances for property testing. +func ConfigurationOperatorSpecGenerator() gopter.Gen { + if configurationOperatorSpecGenerator != nil { + return configurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + configurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ConfigurationOperatorSpec{}), generators) + + return configurationOperatorSpecGenerator +} + func Test_Configuration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForConfiguration_Spec(subject Configuration_Spec) s var configuration_SpecGenerator gopter.Gen // Configuration_SpecGenerator returns a generator of Configuration_Spec instances for property testing. +// We first initialize configuration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Configuration_SpecGenerator() gopter.Gen { if configuration_SpecGenerator != nil { return configuration_SpecGenerator @@ -369,6 +469,12 @@ func Configuration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForConfiguration_Spec(generators) configuration_SpecGenerator = gen.Struct(reflect.TypeOf(Configuration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForConfiguration_Spec(generators) + configuration_SpecGenerator = gen.Struct(reflect.TypeOf(Configuration_Spec{}), generators) + return configuration_SpecGenerator } @@ -378,3 +484,8 @@ func AddIndependentPropertyGeneratorsForConfiguration_Spec(gens map[string]gopte gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformariadb/v1api20180601/database_types_gen.go b/v2/api/dbformariadb/v1api20180601/database_types_gen.go index 4c2539beb8a..5e480156e23 100644 --- a/v2/api/dbformariadb/v1api20180601/database_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *Database) defaultAzureName() { // defaultImpl applies the code generated defaults to the Database resource func (database *Database) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &Database{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *Database) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Database{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *Database) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Database{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *Database) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (database *Database) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (database *Database) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *Database) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (database *Database) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(database) @@ -244,6 +281,14 @@ func (database *Database) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *Database) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *Database) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Database) @@ -336,6 +381,10 @@ type Database_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -403,6 +452,8 @@ func (database *Database_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -475,6 +526,18 @@ func (database *Database_Spec) AssignProperties_From_Database_Spec(source *stora // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_DatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -501,6 +564,18 @@ func (database *Database_Spec) AssignProperties_To_Database_Spec(destination *st // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.DatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_DatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -730,6 +805,110 @@ func (database *Database_STATUS) AssignProperties_To_Database_STATUS(destination return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DatabaseOperatorSpec populates our DatabaseOperatorSpec from the provided source DatabaseOperatorSpec +func (operator *DatabaseOperatorSpec) AssignProperties_From_DatabaseOperatorSpec(source *storage.DatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DatabaseOperatorSpec populates the provided destination DatabaseOperatorSpec from our DatabaseOperatorSpec +func (operator *DatabaseOperatorSpec) AssignProperties_To_DatabaseOperatorSpec(destination *storage.DatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&Database{}, &DatabaseList{}) } diff --git a/v2/api/dbformariadb/v1api20180601/database_types_gen_test.go b/v2/api/dbformariadb/v1api20180601/database_types_gen_test.go index 8c798199ba4..02e4b6f76f1 100644 --- a/v2/api/dbformariadb/v1api20180601/database_types_gen_test.go +++ b/v2/api/dbformariadb/v1api20180601/database_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDatabase(gens map[string]gopter.Gen) { gens["Status"] = Database_STATUSGenerator() } +func Test_DatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DatabaseOperatorSpec to DatabaseOperatorSpec via AssignProperties_To_DatabaseOperatorSpec & AssignProperties_From_DatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDatabaseOperatorSpec, DatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDatabaseOperatorSpec tests if a specific instance of DatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDatabaseOperatorSpec(subject DatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DatabaseOperatorSpec + err := copied.AssignProperties_To_DatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DatabaseOperatorSpec + err = actual.AssignProperties_From_DatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDatabaseOperatorSpec, DatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDatabaseOperatorSpec runs a test to see if a specific instance of DatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDatabaseOperatorSpec(subject DatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DatabaseOperatorSpec instances for property testing - lazily instantiated by +// DatabaseOperatorSpecGenerator() +var databaseOperatorSpecGenerator gopter.Gen + +// DatabaseOperatorSpecGenerator returns a generator of DatabaseOperatorSpec instances for property testing. +func DatabaseOperatorSpecGenerator() gopter.Gen { + if databaseOperatorSpecGenerator != nil { + return databaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + databaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DatabaseOperatorSpec{}), generators) + + return databaseOperatorSpecGenerator +} + func Test_Database_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -355,6 +452,9 @@ func RunJSONSerializationTestForDatabase_Spec(subject Database_Spec) string { var database_SpecGenerator gopter.Gen // Database_SpecGenerator returns a generator of Database_Spec instances for property testing. +// We first initialize database_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Database_SpecGenerator() gopter.Gen { if database_SpecGenerator != nil { return database_SpecGenerator @@ -364,6 +464,12 @@ func Database_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForDatabase_Spec(generators) database_SpecGenerator = gen.Struct(reflect.TypeOf(Database_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForDatabase_Spec(generators) + database_SpecGenerator = gen.Struct(reflect.TypeOf(Database_Spec{}), generators) + return database_SpecGenerator } @@ -373,3 +479,8 @@ func AddIndependentPropertyGeneratorsForDatabase_Spec(gens map[string]gopter.Gen gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformariadb/v1api20180601/server_types_gen.go b/v2/api/dbformariadb/v1api20180601/server_types_gen.go index 19fb8e0f5f7..b0370e31487 100644 --- a/v2/api/dbformariadb/v1api20180601/server_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/server_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (server *Server) defaultAzureName() { // defaultImpl applies the code generated defaults to the Server resource func (server *Server) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &Server{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *Server) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Server{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *Server) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Server{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (server *Server) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (server *Server) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (server *Server) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return server.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (server *Server) validateConfigMapDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(server, nil, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,13 +286,13 @@ func (server *Server) validateSecretDestinations() (admission.Warnings, error) { if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1313,6 +1346,12 @@ var publicNetworkAccess_STATUS_Values = map[string]PublicNetworkAccess_STATUS{ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *ServerOperatorSecrets `json:"secrets,omitempty"` } @@ -1320,6 +1359,42 @@ type ServerOperatorSpec struct { // AssignProperties_From_ServerOperatorSpec populates our ServerOperatorSpec from the provided source ServerOperatorSpec func (operator *ServerOperatorSpec) AssignProperties_From_ServerOperatorSpec(source *storage.ServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret ServerOperatorSecrets @@ -1341,6 +1416,42 @@ func (operator *ServerOperatorSpec) AssignProperties_To_ServerOperatorSpec(desti // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.ServerOperatorSecrets diff --git a/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen.go b/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen.go index a6d284d2115..a437a48fdeb 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (configuration *Configuration) SetConditions(conditions conditions.Conditio configuration.Status.Conditions = conditions } +var _ configmaps.Exporter = &Configuration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *Configuration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Configuration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *Configuration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Configuration{} // AzureName returns the Azure name of the resource @@ -147,8 +170,9 @@ const APIVersion_Value = APIVersion("2018-06-01") type Configuration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *ConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -215,6 +239,14 @@ func (configuration *Configuration_STATUS) ConvertStatusTo(destination genruntim return destination.ConvertStatusFrom(configuration) } +// Storage version of v1api20180601.ConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&Configuration{}, &ConfigurationList{}) } diff --git a/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen_test.go b/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen_test.go index eeeba659179..28994d44565 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen_test.go +++ b/v2/api/dbformariadb/v1api20180601/storage/configuration_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForConfiguration(gens map[string]gopter.Gen) { gens["Status"] = Configuration_STATUSGenerator() } +func Test_ConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForConfigurationOperatorSpec, ConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForConfigurationOperatorSpec runs a test to see if a specific instance of ConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForConfigurationOperatorSpec(subject ConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ConfigurationOperatorSpec instances for property testing - lazily instantiated by +// ConfigurationOperatorSpecGenerator() +var configurationOperatorSpecGenerator gopter.Gen + +// ConfigurationOperatorSpecGenerator returns a generator of ConfigurationOperatorSpec instances for property testing. +func ConfigurationOperatorSpecGenerator() gopter.Gen { + if configurationOperatorSpecGenerator != nil { + return configurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + configurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ConfigurationOperatorSpec{}), generators) + + return configurationOperatorSpecGenerator +} + func Test_Configuration_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -190,6 +245,9 @@ func RunJSONSerializationTestForConfiguration_Spec(subject Configuration_Spec) s var configuration_SpecGenerator gopter.Gen // Configuration_SpecGenerator returns a generator of Configuration_Spec instances for property testing. +// We first initialize configuration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Configuration_SpecGenerator() gopter.Gen { if configuration_SpecGenerator != nil { return configuration_SpecGenerator @@ -199,6 +257,12 @@ func Configuration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForConfiguration_Spec(generators) configuration_SpecGenerator = gen.Struct(reflect.TypeOf(Configuration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForConfiguration_Spec(generators) + configuration_SpecGenerator = gen.Struct(reflect.TypeOf(Configuration_Spec{}), generators) + return configuration_SpecGenerator } @@ -209,3 +273,8 @@ func AddIndependentPropertyGeneratorsForConfiguration_Spec(gens map[string]gopte gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformariadb/v1api20180601/storage/database_types_gen.go b/v2/api/dbformariadb/v1api20180601/storage/database_types_gen.go index b55486a7fb2..adcb63b8819 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/database_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/storage/database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *Database) SetConditions(conditions conditions.Conditions) { database.Status.Conditions = conditions } +var _ configmaps.Exporter = &Database{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *Database) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Database{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *Database) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Database{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type DatabaseList struct { type Database_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *DatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (database *Database_STATUS) ConvertStatusTo(destination genruntime.Converti return destination.ConvertStatusFrom(database) } +// Storage version of v1api20180601.DatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&Database{}, &DatabaseList{}) } diff --git a/v2/api/dbformariadb/v1api20180601/storage/database_types_gen_test.go b/v2/api/dbformariadb/v1api20180601/storage/database_types_gen_test.go index aea7d195df7..257978edf8f 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/database_types_gen_test.go +++ b/v2/api/dbformariadb/v1api20180601/storage/database_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDatabase(gens map[string]gopter.Gen) { gens["Status"] = Database_STATUSGenerator() } +func Test_DatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDatabaseOperatorSpec, DatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDatabaseOperatorSpec runs a test to see if a specific instance of DatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDatabaseOperatorSpec(subject DatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DatabaseOperatorSpec instances for property testing - lazily instantiated by +// DatabaseOperatorSpecGenerator() +var databaseOperatorSpecGenerator gopter.Gen + +// DatabaseOperatorSpecGenerator returns a generator of DatabaseOperatorSpec instances for property testing. +func DatabaseOperatorSpecGenerator() gopter.Gen { + if databaseOperatorSpecGenerator != nil { + return databaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + databaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DatabaseOperatorSpec{}), generators) + + return databaseOperatorSpecGenerator +} + func Test_Database_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -185,6 +240,9 @@ func RunJSONSerializationTestForDatabase_Spec(subject Database_Spec) string { var database_SpecGenerator gopter.Gen // Database_SpecGenerator returns a generator of Database_Spec instances for property testing. +// We first initialize database_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Database_SpecGenerator() gopter.Gen { if database_SpecGenerator != nil { return database_SpecGenerator @@ -194,6 +252,12 @@ func Database_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForDatabase_Spec(generators) database_SpecGenerator = gen.Struct(reflect.TypeOf(Database_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForDatabase_Spec(generators) + database_SpecGenerator = gen.Struct(reflect.TypeOf(Database_Spec{}), generators) + return database_SpecGenerator } @@ -204,3 +268,8 @@ func AddIndependentPropertyGeneratorsForDatabase_Spec(gens map[string]gopter.Gen gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformariadb/v1api20180601/storage/server_types_gen.go b/v2/api/dbformariadb/v1api20180601/storage/server_types_gen.go index f4c3374ddcc..4bc501030ac 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/server_types_gen.go +++ b/v2/api/dbformariadb/v1api20180601/storage/server_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (server *Server) SetConditions(conditions conditions.Conditions) { server.Status.Conditions = conditions } +var _ configmaps.Exporter = &Server{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *Server) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Server{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *Server) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Server{} // AzureName returns the Azure name of the resource @@ -227,8 +250,10 @@ func (server *Server_STATUS) ConvertStatusTo(destination genruntime.ConvertibleS // Storage version of v1api20180601.ServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ServerOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *ServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *ServerOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20180601.ServerPrivateEndpointConnection_STATUS diff --git a/v2/api/dbformariadb/v1api20180601/storage/structure.txt b/v2/api/dbformariadb/v1api20180601/storage/structure.txt index 8939f1a5174..79f5fe89570 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/structure.txt +++ b/v2/api/dbformariadb/v1api20180601/storage/structure.txt @@ -5,8 +5,12 @@ APIVersion: Enum (1 value) └── "2018-06-01" Configuration: Resource ├── Owner: dbformariadb/v1api20180601.Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -26,10 +30,14 @@ Configuration: Resource └── Value: *string Database: Resource ├── Owner: dbformariadb/v1api20180601.Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -46,8 +54,10 @@ Server: Resource ├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/dbformariadb/v1api20180601/storage/zz_generated.deepcopy.go b/v2/api/dbformariadb/v1api20180601/storage/zz_generated.deepcopy.go index 314c8e0e353..9964e45b1c5 100644 --- a/v2/api/dbformariadb/v1api20180601/storage/zz_generated.deepcopy.go +++ b/v2/api/dbformariadb/v1api20180601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *ConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigurationOperatorSpec) DeepCopyInto(out *ConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationOperatorSpec. +func (in *ConfigurationOperatorSpec) DeepCopy() *ConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(ConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Configuration_STATUS) DeepCopyInto(out *Configuration_STATUS) { *out = *in @@ -151,6 +196,11 @@ func (in *Configuration_STATUS) DeepCopy() *Configuration_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Configuration_Spec) DeepCopyInto(out *Configuration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -244,6 +294,50 @@ func (in *DatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseOperatorSpec) DeepCopyInto(out *DatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseOperatorSpec. +func (in *DatabaseOperatorSpec) DeepCopy() *DatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(DatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Database_STATUS) DeepCopyInto(out *Database_STATUS) { *out = *in @@ -311,6 +405,11 @@ func (in *Database_Spec) DeepCopyInto(out *Database_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -451,6 +550,17 @@ func (in *ServerOperatorSecrets) DeepCopy() *ServerOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -458,6 +568,17 @@ func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ServerOperatorSecrets) diff --git a/v2/api/dbformariadb/v1api20180601/structure.txt b/v2/api/dbformariadb/v1api20180601/structure.txt index 27f8b9f3be2..59a0b172b34 100644 --- a/v2/api/dbformariadb/v1api20180601/structure.txt +++ b/v2/api/dbformariadb/v1api20180601/structure.txt @@ -5,8 +5,11 @@ APIVersion: Enum (1 value) └── "2018-06-01" Configuration: Resource ├── Owner: Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *string │ └── Value: *string @@ -23,10 +26,13 @@ Configuration: Resource └── Value: *string Database: Resource ├── Owner: Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (6 properties) ├── Charset: *string @@ -40,7 +46,9 @@ Server: Resource ├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference diff --git a/v2/api/dbformariadb/v1api20180601/zz_generated.deepcopy.go b/v2/api/dbformariadb/v1api20180601/zz_generated.deepcopy.go index efabbc508ba..4bb5cd3716b 100644 --- a/v2/api/dbformariadb/v1api20180601/zz_generated.deepcopy.go +++ b/v2/api/dbformariadb/v1api20180601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *ConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigurationOperatorSpec) DeepCopyInto(out *ConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationOperatorSpec. +func (in *ConfigurationOperatorSpec) DeepCopy() *ConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(ConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Configuration_STATUS) DeepCopyInto(out *Configuration_STATUS) { *out = *in @@ -144,6 +182,11 @@ func (in *Configuration_STATUS) DeepCopy() *Configuration_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Configuration_Spec) DeepCopyInto(out *Configuration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -230,6 +273,43 @@ func (in *DatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseOperatorSpec) DeepCopyInto(out *DatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseOperatorSpec. +func (in *DatabaseOperatorSpec) DeepCopy() *DatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(DatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Database_STATUS) DeepCopyInto(out *Database_STATUS) { *out = *in @@ -290,6 +370,11 @@ func (in *Database_Spec) DeepCopyInto(out *Database_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -409,6 +494,28 @@ func (in *ServerOperatorSecrets) DeepCopy() *ServerOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(ServerOperatorSecrets) diff --git a/v2/api/dbformysql/v1api20210501/flexible_server_types_gen.go b/v2/api/dbformysql/v1api20210501/flexible_server_types_gen.go index b653f9419fe..8b877d46bde 100644 --- a/v2/api/dbformysql/v1api20210501/flexible_server_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/flexible_server_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -112,6 +113,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -273,14 +294,14 @@ func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warning if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.AdministratorLogin, - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.AdministratorLogin, + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -302,13 +323,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2584,9 +2605,15 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -2594,6 +2621,24 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -2606,6 +2651,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -2627,6 +2690,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -2639,6 +2720,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen.go b/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen.go index 1b41fdf14f1..696dd83cb37 100644 --- a/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -339,6 +384,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -406,6 +455,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -478,6 +529,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -760,6 +835,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen_test.go b/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen_test.go index 4d05dccade0..9f99a3c580d 100644 --- a/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbformysql/v1api20210501/flexible_servers_database_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210501s.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen.go index f22c2e9bb58..fc8376ebece 100644 --- a/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -338,6 +383,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -401,6 +450,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -484,6 +535,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -520,6 +583,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -784,6 +859,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen_test.go index 03cac5b10af..1b842f253fb 100644 --- a/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbformysql/v1api20210501/flexible_servers_firewall_rule_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210501s.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20210501/storage/flexible_server_types_gen.go b/v2/api/dbformysql/v1api20210501/storage/flexible_server_types_gen.go index 719cbf0c5a3..1ea866d5eba 100644 --- a/v2/api/dbformysql/v1api20210501/storage/flexible_server_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/storage/flexible_server_types_gen.go @@ -12,6 +12,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -72,6 +74,26 @@ func (server *FlexibleServer) ConvertTo(hub conversion.Hub) error { return server.AssignProperties_To_FlexibleServer(destination) } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -1628,9 +1650,11 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Storage version of v1api20210501.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec @@ -1638,6 +1662,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -1650,6 +1692,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -1687,6 +1747,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap v20230630s.FlexibleServerOperatorConfigMaps @@ -1699,6 +1777,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20230630s.FlexibleServerOperatorSecrets diff --git a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen.go b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen.go index 722499be837..244b6f2f692 100644 --- a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen.go @@ -9,6 +9,9 @@ import ( v20230630s "github.com/Azure/azure-service-operator/v2/api/dbformysql/v1api20230630/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -66,6 +69,26 @@ func (database *FlexibleServersDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_FlexibleServersDatabase(destination) } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -236,10 +259,11 @@ type augmentConversionForFlexibleServersDatabase interface { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -313,6 +337,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // OriginalVersion database.OriginalVersion = source.OriginalVersion @@ -358,6 +394,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec v20230630s.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion @@ -581,6 +629,141 @@ type augmentConversionForFlexibleServersDatabase_STATUS interface { AssignPropertiesTo(dst *v20230630s.FlexibleServersDatabase_STATUS) error } +// Storage version of v1api20210501.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *v20230630s.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *v20230630s.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *v20230630s.FlexibleServersDatabaseOperatorSpec) error + AssignPropertiesTo(dst *v20230630s.FlexibleServersDatabaseOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen_test.go index 1a80baaa40d..67f9037fbf4 100644 --- a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_database_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen.go index 2d1c476a0d7..9be2c15c6bd 100644 --- a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen.go @@ -9,6 +9,9 @@ import ( v20230630s "github.com/Azure/azure-service-operator/v2/api/dbformysql/v1api20230630/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -66,6 +69,26 @@ func (rule *FlexibleServersFirewallRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_FlexibleServersFirewallRule(destination) } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -236,9 +259,10 @@ type augmentConversionForFlexibleServersFirewallRule interface { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -310,6 +334,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ // EndIpAddress rule.EndIpAddress = genruntime.ClonePointerToString(source.EndIpAddress) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -355,6 +391,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer // EndIpAddress destination.EndIpAddress = genruntime.ClonePointerToString(rule.EndIpAddress) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec v20230630s.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -581,6 +629,141 @@ type augmentConversionForFlexibleServersFirewallRule_STATUS interface { AssignPropertiesTo(dst *v20230630s.FlexibleServersFirewallRule_STATUS) error } +// Storage version of v1api20210501.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *v20230630s.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *v20230630s.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *v20230630s.FlexibleServersFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *v20230630s.FlexibleServersFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen_test.go index 8e989043bcd..8b15f3191eb 100644 --- a/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbformysql/v1api20210501/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20210501/storage/structure.txt b/v2/api/dbformysql/v1api20210501/storage/structure.txt index ecbe827dea3..8ad5c6acc37 100644 --- a/v2/api/dbformysql/v1api20210501/storage/structure.txt +++ b/v2/api/dbformysql/v1api20210501/storage/structure.txt @@ -43,12 +43,14 @@ FlexibleServer: Resource │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ ├── PrivateDnsZoneResourceReference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── AdministratorLogin: *genruntime.ConfigMapDestination │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -141,10 +143,14 @@ FlexibleServer: Resource └── Version: *string FlexibleServersDatabase: Resource ├── Owner: dbformysql/v1api20210501.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -166,9 +172,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbformysql/v1api20210501.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -200,9 +210,11 @@ augmentConversionForFlexibleServerOperatorSpec: Interface augmentConversionForFlexibleServer_STATUS: Interface augmentConversionForFlexibleServer_Spec: Interface augmentConversionForFlexibleServersDatabase: Interface +augmentConversionForFlexibleServersDatabaseOperatorSpec: Interface augmentConversionForFlexibleServersDatabase_STATUS: Interface augmentConversionForFlexibleServersDatabase_Spec: Interface augmentConversionForFlexibleServersFirewallRule: Interface +augmentConversionForFlexibleServersFirewallRuleOperatorSpec: Interface augmentConversionForFlexibleServersFirewallRule_STATUS: Interface augmentConversionForFlexibleServersFirewallRule_Spec: Interface augmentConversionForHighAvailability: Interface diff --git a/v2/api/dbformysql/v1api20210501/storage/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20210501/storage/zz_generated.deepcopy.go index 98e31c7b300..42f1af62f10 100644 --- a/v2/api/dbformysql/v1api20210501/storage/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20210501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -300,6 +301,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) @@ -312,6 +324,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -663,6 +686,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -735,6 +802,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -818,6 +890,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -885,6 +1001,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformysql/v1api20210501/structure.txt b/v2/api/dbformysql/v1api20210501/structure.txt index 29e50ca0607..07d875c9608 100644 --- a/v2/api/dbformysql/v1api20210501/structure.txt +++ b/v2/api/dbformysql/v1api20210501/structure.txt @@ -48,10 +48,12 @@ FlexibleServer: Resource │ ├── Network: *Object (2 properties) │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ └── PrivateDnsZoneResourceReference: *genruntime.ResourceReference -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── AdministratorLogin: *genruntime.ConfigMapDestination │ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -183,10 +185,13 @@ FlexibleServer: Resource └── "8.0.21" FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -212,10 +217,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbformysql/v1api20210501/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20210501/zz_generated.deepcopy.go index 583fe933c41..5c163288350 100644 --- a/v2/api/dbformysql/v1api20210501/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20210501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -258,11 +259,33 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -600,6 +623,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -665,6 +725,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -741,6 +806,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -801,6 +903,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen.go b/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen.go index 9a64f4f3d71..11963d95298 100644 --- a/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen.go +++ b/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -99,6 +101,26 @@ func (administrator *FlexibleServersAdministrator) Default() { // defaultImpl applies the code generated defaults to the FlexibleServersAdministrator resource func (administrator *FlexibleServersAdministrator) defaultImpl() {} +var _ configmaps.Exporter = &FlexibleServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *FlexibleServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *FlexibleServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersAdministrator{} // AzureName returns the Azure name of the resource (always "ActiveDirectory") @@ -206,7 +228,7 @@ func (administrator *FlexibleServersAdministrator) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (administrator *FlexibleServersAdministrator) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateSecretDestinations, administrator.validateConfigMapDestinations, administrator.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -224,12 +246,26 @@ func (administrator *FlexibleServersAdministrator) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (administrator *FlexibleServersAdministrator) validateConfigMapDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (administrator *FlexibleServersAdministrator) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&administrator.Spec) @@ -253,6 +289,14 @@ func (administrator *FlexibleServersAdministrator) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (administrator *FlexibleServersAdministrator) validateSecretDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (administrator *FlexibleServersAdministrator) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersAdministrator) @@ -349,6 +393,10 @@ type FlexibleServersAdministrator_Spec struct { // Login: Login name of the server administrator. Login *string `json:"login,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -469,6 +517,8 @@ func (administrator *FlexibleServersAdministrator_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": administrator.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -574,6 +624,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_From_Fl // Login administrator.Login = genruntime.ClonePointerToString(source.Login) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersAdministratorOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + administrator.OperatorSpec = &operatorSpec + } else { + administrator.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -632,6 +694,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_To_Flex // Login destination.Login = genruntime.ClonePointerToString(administrator.Login) + // OperatorSpec + if administrator.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersAdministratorOperatorSpec + err := administrator.OperatorSpec.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = administrator.OriginalVersion() @@ -991,6 +1065,110 @@ var administratorProperties_AdministratorType_STATUS_Values = map[string]Adminis "activedirectory": AdministratorProperties_AdministratorType_STATUS_ActiveDirectory, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersAdministratorOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersAdministratorOperatorSpec populates our FlexibleServersAdministratorOperatorSpec from the provided source FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source *storage.FlexibleServersAdministratorOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersAdministratorOperatorSpec populates the provided destination FlexibleServersAdministratorOperatorSpec from our FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_To_FlexibleServersAdministratorOperatorSpec(destination *storage.FlexibleServersAdministratorOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen_test.go b/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen_test.go index 00dde3d05d2..0589e6dc7e2 100644 --- a/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen_test.go +++ b/v2/api/dbformysql/v1api20220101/flexible_servers_administrator_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator(gens map[string gens["Status"] = FlexibleServersAdministrator_STATUSGenerator() } +func Test_FlexibleServersAdministratorOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersAdministratorOperatorSpec to FlexibleServersAdministratorOperatorSpec via AssignProperties_To_FlexibleServersAdministratorOperatorSpec & AssignProperties_From_FlexibleServersAdministratorOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec tests if a specific instance of FlexibleServersAdministratorOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220101s.FlexibleServersAdministratorOperatorSpec + err := copied.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersAdministratorOperatorSpec + err = actual.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec runs a test to see if a specific instance of FlexibleServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersAdministratorOperatorSpecGenerator() +var flexibleServersAdministratorOperatorSpecGenerator gopter.Gen + +// FlexibleServersAdministratorOperatorSpecGenerator returns a generator of FlexibleServersAdministratorOperatorSpec instances for property testing. +func FlexibleServersAdministratorOperatorSpecGenerator() gopter.Gen { + if flexibleServersAdministratorOperatorSpecGenerator != nil { + return flexibleServersAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministratorOperatorSpec{}), generators) + + return flexibleServersAdministratorOperatorSpecGenerator +} + func Test_FlexibleServersAdministrator_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -376,6 +473,9 @@ func RunJSONSerializationTestForFlexibleServersAdministrator_Spec(subject Flexib var flexibleServersAdministrator_SpecGenerator gopter.Gen // FlexibleServersAdministrator_SpecGenerator returns a generator of FlexibleServersAdministrator_Spec instances for property testing. +// We first initialize flexibleServersAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { if flexibleServersAdministrator_SpecGenerator != nil { return flexibleServersAdministrator_SpecGenerator @@ -385,6 +485,12 @@ func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + return flexibleServersAdministrator_SpecGenerator } @@ -396,6 +502,11 @@ func AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens m gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersAdministratorOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen.go b/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen.go index ad6e9e4e036..b7b1135682c 100644 --- a/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -211,7 +234,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -336,6 +381,10 @@ type FlexibleServersConfiguration_Spec struct { // CurrentValue: Current value of the configuration. CurrentValue *string `json:"currentValue,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -408,6 +457,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -497,6 +548,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // CurrentValue configuration.CurrentValue = genruntime.ClonePointerToString(source.CurrentValue) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -532,6 +595,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // CurrentValue destination.CurrentValue = genruntime.ClonePointerToString(configuration.CurrentValue) + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -1079,6 +1154,110 @@ var configurationProperties_Source_STATUS_Values = map[string]ConfigurationPrope "user-override": ConfigurationProperties_Source_STATUS_UserOverride, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen_test.go b/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen_test.go index 1d9100f0bb3..9b67aec758b 100644 --- a/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbformysql/v1api20220101/flexible_servers_configuration_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220101s.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -382,6 +479,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -391,6 +491,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -401,3 +507,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.OneConstOf(ConfigurationProperties_Source_SystemDefault, ConfigurationProperties_Source_UserOverride)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen.go b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen.go index 8e54ef359b0..a3bebcabe57 100644 --- a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen.go +++ b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbformysql/v1api20230630/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (administrator *FlexibleServersAdministrator) ConvertTo(hub conversion.Hub) return administrator.AssignProperties_To_FlexibleServersAdministrator(destination) } +var _ configmaps.Exporter = &FlexibleServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *FlexibleServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *FlexibleServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersAdministrator{} // AzureName returns the Azure name of the resource (always "ActiveDirectory") @@ -242,9 +265,10 @@ type FlexibleServersAdministrator_Spec struct { AdministratorType *string `json:"administratorType,omitempty"` // IdentityResourceReference: The resource id of the identity used for AAD Authentication. - IdentityResourceReference *genruntime.ResourceReference `armReference:"IdentityResourceId" json:"identityResourceReference,omitempty"` - Login *string `json:"login,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + IdentityResourceReference *genruntime.ResourceReference `armReference:"IdentityResourceId" json:"identityResourceReference,omitempty"` + Login *string `json:"login,omitempty"` + OperatorSpec *FlexibleServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -327,6 +351,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_From_Fl // Login administrator.Login = genruntime.ClonePointerToString(source.Login) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersAdministratorOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + administrator.OperatorSpec = &operatorSpec + } else { + administrator.OperatorSpec = nil + } + // OriginalVersion administrator.OriginalVersion = source.OriginalVersion @@ -399,6 +435,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_To_Flex // Login destination.Login = genruntime.ClonePointerToString(administrator.Login) + // OperatorSpec + if administrator.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersAdministratorOperatorSpec + err := administrator.OperatorSpec.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = administrator.OriginalVersion @@ -655,6 +703,136 @@ type augmentConversionForFlexibleServersAdministrator_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersAdministrator_STATUS) error } +// Storage version of v1api20220101.FlexibleServersAdministratorOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersAdministratorOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersAdministratorOperatorSpec populates our FlexibleServersAdministratorOperatorSpec from the provided source FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source *storage.FlexibleServersAdministratorOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersAdministratorOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersAdministratorOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersAdministratorOperatorSpec populates the provided destination FlexibleServersAdministratorOperatorSpec from our FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_To_FlexibleServersAdministratorOperatorSpec(destination *storage.FlexibleServersAdministratorOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersAdministratorOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersAdministratorOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20220101.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { @@ -753,6 +931,11 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination return nil } +type augmentConversionForFlexibleServersAdministratorOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersAdministratorOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersAdministratorOperatorSpec) error +} + type augmentConversionForSystemData_STATUS interface { AssignPropertiesFrom(src *storage.SystemData_STATUS) error AssignPropertiesTo(dst *storage.SystemData_STATUS) error diff --git a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen_test.go b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen_test.go index c624909228d..cc156adac5b 100644 --- a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen_test.go +++ b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_administrator_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator(gens map[string gens["Status"] = FlexibleServersAdministrator_STATUSGenerator() } +func Test_FlexibleServersAdministratorOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersAdministratorOperatorSpec to FlexibleServersAdministratorOperatorSpec via AssignProperties_To_FlexibleServersAdministratorOperatorSpec & AssignProperties_From_FlexibleServersAdministratorOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec tests if a specific instance of FlexibleServersAdministratorOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersAdministratorOperatorSpec + err := copied.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersAdministratorOperatorSpec + err = actual.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec runs a test to see if a specific instance of FlexibleServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersAdministratorOperatorSpecGenerator() +var flexibleServersAdministratorOperatorSpecGenerator gopter.Gen + +// FlexibleServersAdministratorOperatorSpecGenerator returns a generator of FlexibleServersAdministratorOperatorSpec instances for property testing. +func FlexibleServersAdministratorOperatorSpecGenerator() gopter.Gen { + if flexibleServersAdministratorOperatorSpecGenerator != nil { + return flexibleServersAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministratorOperatorSpec{}), generators) + + return flexibleServersAdministratorOperatorSpecGenerator +} + func Test_FlexibleServersAdministrator_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -375,6 +472,9 @@ func RunJSONSerializationTestForFlexibleServersAdministrator_Spec(subject Flexib var flexibleServersAdministrator_SpecGenerator gopter.Gen // FlexibleServersAdministrator_SpecGenerator returns a generator of FlexibleServersAdministrator_Spec instances for property testing. +// We first initialize flexibleServersAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { if flexibleServersAdministrator_SpecGenerator != nil { return flexibleServersAdministrator_SpecGenerator @@ -384,6 +484,12 @@ func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + return flexibleServersAdministrator_SpecGenerator } @@ -396,6 +502,11 @@ func AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens m gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersAdministratorOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen.go index 0962f861968..7fb5d8316c5 100644 --- a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbformysql/v1api20230630/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (configuration *FlexibleServersConfiguration) ConvertTo(hub conversion.Hub) return configuration.AssignProperties_To_FlexibleServersConfiguration(destination) } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -234,9 +257,10 @@ type augmentConversionForFlexibleServersConfiguration interface { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CurrentValue *string `json:"currentValue,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CurrentValue *string `json:"currentValue,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -309,6 +333,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // CurrentValue configuration.CurrentValue = genruntime.ClonePointerToString(source.CurrentValue) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // OriginalVersion configuration.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // CurrentValue destination.CurrentValue = genruntime.ClonePointerToString(configuration.CurrentValue) + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion @@ -639,6 +687,141 @@ type augmentConversionForFlexibleServersConfiguration_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersConfiguration_STATUS) error } +// Storage version of v1api20220101.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersConfigurationOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersConfigurationOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersConfigurationOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen_test.go index e62e921c58d..240f0e8271e 100644 --- a/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbformysql/v1api20220101/storage/flexible_servers_configuration_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -381,6 +478,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -390,6 +490,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -401,3 +507,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20220101/storage/structure.txt b/v2/api/dbformysql/v1api20220101/storage/structure.txt index 1b8d2f95c77..72975f10a10 100644 --- a/v2/api/dbformysql/v1api20220101/storage/structure.txt +++ b/v2/api/dbformysql/v1api20220101/storage/structure.txt @@ -5,10 +5,14 @@ APIVersion: Enum (1 value) └── "2022-01-01" FlexibleServersAdministrator: Resource ├── Owner: dbformysql/v1api20220101.FlexibleServer -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AdministratorType: *string │ ├── IdentityResourceReference: *genruntime.ResourceReference │ ├── Login: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -37,9 +41,13 @@ FlexibleServersAdministrator: Resource └── Type: *string FlexibleServersConfiguration: Resource ├── Owner: dbformysql/v1api20220101.FlexibleServer -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── CurrentValue: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -71,9 +79,11 @@ FlexibleServersConfiguration: Resource ├── Type: *string └── Value: *string augmentConversionForFlexibleServersAdministrator: Interface +augmentConversionForFlexibleServersAdministratorOperatorSpec: Interface augmentConversionForFlexibleServersAdministrator_STATUS: Interface augmentConversionForFlexibleServersAdministrator_Spec: Interface augmentConversionForFlexibleServersConfiguration: Interface +augmentConversionForFlexibleServersConfigurationOperatorSpec: Interface augmentConversionForFlexibleServersConfiguration_STATUS: Interface augmentConversionForFlexibleServersConfiguration_Spec: Interface augmentConversionForSystemData_STATUS: Interface diff --git a/v2/api/dbformysql/v1api20220101/storage/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20220101/storage/zz_generated.deepcopy.go index 91e59c96221..fd99ef35918 100644 --- a/v2/api/dbformysql/v1api20220101/storage/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20220101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *FlexibleServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopyInto(out *FlexibleServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersAdministratorOperatorSpec. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopy() *FlexibleServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersAdministrator_STATUS) DeepCopyInto(out *FlexibleServersAdministrator_STATUS) { *out = *in @@ -166,6 +211,11 @@ func (in *FlexibleServersAdministrator_Spec) DeepCopyInto(out *FlexibleServersAd *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -269,6 +319,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -381,6 +475,11 @@ func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersCo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformysql/v1api20220101/structure.txt b/v2/api/dbformysql/v1api20220101/structure.txt index 243e4a689db..5a08757a5df 100644 --- a/v2/api/dbformysql/v1api20220101/structure.txt +++ b/v2/api/dbformysql/v1api20220101/structure.txt @@ -5,11 +5,14 @@ APIVersion: Enum (1 value) └── "2022-01-01" FlexibleServersAdministrator: Resource ├── Owner: FlexibleServer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AdministratorType: *Enum (1 value) │ │ └── "ActiveDirectory" │ ├── IdentityResourceReference: *genruntime.ResourceReference │ ├── Login: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sid: *string │ ├── SidFromConfig: *genruntime.ConfigMapReference @@ -43,10 +46,13 @@ FlexibleServersAdministrator: Resource └── Type: *string FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z0-9_.-]+$" │ ├── CurrentValue: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *Enum (2 values) │ │ ├── "system-default" diff --git a/v2/api/dbformysql/v1api20220101/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20220101/zz_generated.deepcopy.go index 5aa480347cb..58cfe84b4de 100644 --- a/v2/api/dbformysql/v1api20220101/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20220101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *FlexibleServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopyInto(out *FlexibleServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersAdministratorOperatorSpec. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopy() *FlexibleServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersAdministrator_STATUS) DeepCopyInto(out *FlexibleServersAdministrator_STATUS) { *out = *in @@ -159,6 +197,11 @@ func (in *FlexibleServersAdministrator_Spec) DeepCopyInto(out *FlexibleServersAd *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -255,6 +298,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -360,6 +440,11 @@ func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersCo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformysql/v1api20230630/flexible_server_types_gen.go b/v2/api/dbformysql/v1api20230630/flexible_server_types_gen.go index 49d70858124..a9c32eac250 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_server_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/flexible_server_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -98,6 +99,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServer{} // InitializeSpec initializes the spec for this resource from the given status @@ -270,14 +291,14 @@ func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warning if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.AdministratorLogin, - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.AdministratorLogin, + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -299,13 +320,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2948,9 +2969,15 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -2958,6 +2985,24 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -2970,6 +3015,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -2991,6 +3054,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -3003,6 +3084,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen.go b/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen.go index bd8c6653361..c35a7482d69 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (administrator *FlexibleServersAdministrator) Default() { // defaultImpl applies the code generated defaults to the FlexibleServersAdministrator resource func (administrator *FlexibleServersAdministrator) defaultImpl() {} +var _ configmaps.Exporter = &FlexibleServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *FlexibleServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *FlexibleServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersAdministrator{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +225,7 @@ func (administrator *FlexibleServersAdministrator) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (administrator *FlexibleServersAdministrator) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateSecretDestinations, administrator.validateConfigMapDestinations, administrator.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -221,12 +243,26 @@ func (administrator *FlexibleServersAdministrator) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (administrator *FlexibleServersAdministrator) validateConfigMapDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (administrator *FlexibleServersAdministrator) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&administrator.Spec) @@ -250,6 +286,14 @@ func (administrator *FlexibleServersAdministrator) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (administrator *FlexibleServersAdministrator) validateSecretDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (administrator *FlexibleServersAdministrator) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersAdministrator) @@ -341,6 +385,10 @@ type FlexibleServersAdministrator_Spec struct { // Login: Login name of the server administrator. Login *string `json:"login,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -461,6 +509,8 @@ func (administrator *FlexibleServersAdministrator_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": administrator.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -566,6 +616,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_From_Fl // Login administrator.Login = genruntime.ClonePointerToString(source.Login) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersAdministratorOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + administrator.OperatorSpec = &operatorSpec + } else { + administrator.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -624,6 +686,18 @@ func (administrator *FlexibleServersAdministrator_Spec) AssignProperties_To_Flex // Login destination.Login = genruntime.ClonePointerToString(administrator.Login) + // OperatorSpec + if administrator.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersAdministratorOperatorSpec + err := administrator.OperatorSpec.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = administrator.OriginalVersion() @@ -1015,6 +1089,110 @@ var administratorProperties_AdministratorType_STATUS_Values = map[string]Adminis "activedirectory": AdministratorProperties_AdministratorType_STATUS_ActiveDirectory, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersAdministratorOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersAdministratorOperatorSpec populates our FlexibleServersAdministratorOperatorSpec from the provided source FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_From_FlexibleServersAdministratorOperatorSpec(source *storage.FlexibleServersAdministratorOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersAdministratorOperatorSpec populates the provided destination FlexibleServersAdministratorOperatorSpec from our FlexibleServersAdministratorOperatorSpec +func (operator *FlexibleServersAdministratorOperatorSpec) AssignProperties_To_FlexibleServersAdministratorOperatorSpec(destination *storage.FlexibleServersAdministratorOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersAdministrator{}, &FlexibleServersAdministratorList{}) } diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen_test.go b/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen_test.go index 9bb27f980ae..8187f66682e 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_administrator_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator(gens map[string gens["Status"] = FlexibleServersAdministrator_STATUSGenerator() } +func Test_FlexibleServersAdministratorOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersAdministratorOperatorSpec to FlexibleServersAdministratorOperatorSpec via AssignProperties_To_FlexibleServersAdministratorOperatorSpec & AssignProperties_From_FlexibleServersAdministratorOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec tests if a specific instance of FlexibleServersAdministratorOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersAdministratorOperatorSpec + err := copied.AssignProperties_To_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersAdministratorOperatorSpec + err = actual.AssignProperties_From_FlexibleServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec runs a test to see if a specific instance of FlexibleServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersAdministratorOperatorSpecGenerator() +var flexibleServersAdministratorOperatorSpecGenerator gopter.Gen + +// FlexibleServersAdministratorOperatorSpecGenerator returns a generator of FlexibleServersAdministratorOperatorSpec instances for property testing. +func FlexibleServersAdministratorOperatorSpecGenerator() gopter.Gen { + if flexibleServersAdministratorOperatorSpecGenerator != nil { + return flexibleServersAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministratorOperatorSpec{}), generators) + + return flexibleServersAdministratorOperatorSpecGenerator +} + func Test_FlexibleServersAdministrator_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -375,6 +472,9 @@ func RunJSONSerializationTestForFlexibleServersAdministrator_Spec(subject Flexib var flexibleServersAdministrator_SpecGenerator gopter.Gen // FlexibleServersAdministrator_SpecGenerator returns a generator of FlexibleServersAdministrator_Spec instances for property testing. +// We first initialize flexibleServersAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { if flexibleServersAdministrator_SpecGenerator != nil { return flexibleServersAdministrator_SpecGenerator @@ -384,6 +484,12 @@ func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + return flexibleServersAdministrator_SpecGenerator } @@ -394,3 +500,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens m gens["Sid"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersAdministratorOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen.go b/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen.go index 73c301f95e4..4cff41ee369 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersConfiguration{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -226,7 +249,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -243,6 +280,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -332,6 +377,10 @@ type FlexibleServersConfiguration_Spec struct { // CurrentValue: Current value of the configuration. CurrentValue *string `json:"currentValue,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -404,6 +453,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -493,6 +544,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // CurrentValue configuration.CurrentValue = genruntime.ClonePointerToString(source.CurrentValue) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -528,6 +591,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // CurrentValue destination.CurrentValue = genruntime.ClonePointerToString(configuration.CurrentValue) + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -1096,6 +1171,110 @@ var configurationProperties_Source_STATUS_Values = map[string]ConfigurationPrope "user-override": ConfigurationProperties_Source_STATUS_UserOverride, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen_test.go b/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen_test.go index 4bc32b47fcd..36d232b70c1 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_configuration_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -381,6 +478,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -390,6 +490,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -400,3 +506,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.OneConstOf(ConfigurationProperties_Source_SystemDefault, ConfigurationProperties_Source_UserOverride)) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen.go b/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen.go index 86974cba590..02d950ff0c7 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -336,6 +381,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -403,6 +452,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -475,6 +526,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -501,6 +564,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -770,6 +845,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen_test.go b/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen_test.go index f53a0692af4..d4a167a54ab 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_database_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -390,3 +496,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen.go index 55c22209483..b4d85552c6c 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersFirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -335,6 +380,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -398,6 +447,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -481,6 +532,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -517,6 +580,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -804,6 +879,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen_test.go index bbb4e815c66..9b1cab3d4dd 100644 --- a/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/flexible_servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -390,3 +496,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_server_types_gen.go b/v2/api/dbformysql/v1api20230630/storage/flexible_server_types_gen.go index 46fc133d523..d0acb75231a 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_server_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_server_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -50,6 +52,26 @@ func (server *FlexibleServer) SetConditions(conditions conditions.Conditions) { server.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -329,9 +351,11 @@ type DataEncryption_STATUS struct { // Storage version of v1api20230630.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20230630.HighAvailability diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen.go index e77ca76c526..55ac8af8e8c 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (administrator *FlexibleServersAdministrator) SetConditions(conditions cond administrator.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *FlexibleServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *FlexibleServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersAdministrator{} // AzureName returns the Azure name of the resource (always "ActiveDirectory") @@ -143,9 +166,10 @@ type FlexibleServersAdministrator_Spec struct { AdministratorType *string `json:"administratorType,omitempty"` // IdentityResourceReference: The resource id of the identity used for AAD Authentication. - IdentityResourceReference *genruntime.ResourceReference `armReference:"IdentityResourceId" json:"identityResourceReference,omitempty"` - Login *string `json:"login,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + IdentityResourceReference *genruntime.ResourceReference `armReference:"IdentityResourceId" json:"identityResourceReference,omitempty"` + Login *string `json:"login,omitempty"` + OperatorSpec *FlexibleServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -214,6 +238,14 @@ func (administrator *FlexibleServersAdministrator_STATUS) ConvertStatusTo(destin return destination.ConvertStatusFrom(administrator) } +// Storage version of v1api20230630.FlexibleServersAdministratorOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersAdministratorOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersAdministrator{}, &FlexibleServersAdministratorList{}) } diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen_test.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen_test.go index 19b2944c7af..c06cdd5710a 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_administrator_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator(gens map[string gens["Status"] = FlexibleServersAdministrator_STATUSGenerator() } +func Test_FlexibleServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec, FlexibleServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec runs a test to see if a specific instance of FlexibleServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersAdministratorOperatorSpec(subject FlexibleServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersAdministratorOperatorSpecGenerator() +var flexibleServersAdministratorOperatorSpecGenerator gopter.Gen + +// FlexibleServersAdministratorOperatorSpecGenerator returns a generator of FlexibleServersAdministratorOperatorSpec instances for property testing. +func FlexibleServersAdministratorOperatorSpecGenerator() gopter.Gen { + if flexibleServersAdministratorOperatorSpecGenerator != nil { + return flexibleServersAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministratorOperatorSpec{}), generators) + + return flexibleServersAdministratorOperatorSpecGenerator +} + func Test_FlexibleServersAdministrator_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -205,6 +260,9 @@ func RunJSONSerializationTestForFlexibleServersAdministrator_Spec(subject Flexib var flexibleServersAdministrator_SpecGenerator gopter.Gen // FlexibleServersAdministrator_SpecGenerator returns a generator of FlexibleServersAdministrator_Spec instances for property testing. +// We first initialize flexibleServersAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { if flexibleServersAdministrator_SpecGenerator != nil { return flexibleServersAdministrator_SpecGenerator @@ -214,6 +272,12 @@ func FlexibleServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(generators) + flexibleServersAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersAdministrator_Spec{}), generators) + return flexibleServersAdministrator_SpecGenerator } @@ -225,3 +289,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens m gens["Sid"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersAdministratorOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen.go index 92c74ced669..07dfbe05947 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (configuration *FlexibleServersConfiguration) SetConditions(conditions cond configuration.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -141,9 +164,10 @@ type FlexibleServersConfigurationList struct { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CurrentValue *string `json:"currentValue,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CurrentValue *string `json:"currentValue,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -216,6 +240,14 @@ func (configuration *FlexibleServersConfiguration_STATUS) ConvertStatusTo(destin return destination.ConvertStatusFrom(configuration) } +// Storage version of v1api20230630.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen_test.go index c3a9650b681..e6fa648785b 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_configuration_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -211,6 +266,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -220,6 +278,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -231,3 +295,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen.go index 6ee58de1d2e..79e69739744 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *FlexibleServersDatabase) SetConditions(conditions conditions.Con database.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type FlexibleServersDatabaseList struct { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -207,6 +231,14 @@ func (database *FlexibleServersDatabase_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(database) } +// Storage version of v1api20230630.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen_test.go index 3f82bf2fff1..ef0e4494757 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_database_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -211,6 +269,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen.go index 36ea72e0d75..9f717aa48c4 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *FlexibleServersFirewallRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type FlexibleServersFirewallRuleList struct { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -207,6 +231,14 @@ func (rule *FlexibleServersFirewallRule_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20230630.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen_test.go index 5a71143375c..6130a5e3640 100644 --- a/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbformysql/v1api20230630/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -211,6 +269,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbformysql/v1api20230630/storage/structure.txt b/v2/api/dbformysql/v1api20230630/storage/structure.txt index 32ecdd59706..455a02bf7c7 100644 --- a/v2/api/dbformysql/v1api20230630/storage/structure.txt +++ b/v2/api/dbformysql/v1api20230630/storage/structure.txt @@ -50,12 +50,14 @@ FlexibleServer: Resource │ │ ├── PrivateDnsZoneResourceReference: *genruntime.ResourceReference │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── PublicNetworkAccess: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── AdministratorLogin: *genruntime.ConfigMapDestination │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -160,10 +162,14 @@ FlexibleServer: Resource └── Version: *string FlexibleServersAdministrator: Resource ├── Owner: dbformysql/v1api20230630.FlexibleServer -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AdministratorType: *string │ ├── IdentityResourceReference: *genruntime.ResourceReference │ ├── Login: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -192,9 +198,13 @@ FlexibleServersAdministrator: Resource └── Type: *string FlexibleServersConfiguration: Resource ├── Owner: dbformysql/v1api20230630.FlexibleServer -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── CurrentValue: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -227,10 +237,14 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: dbformysql/v1api20230630.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -252,9 +266,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbformysql/v1api20230630.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/dbformysql/v1api20230630/storage/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20230630/storage/zz_generated.deepcopy.go index 1eec6ecf520..175501b6ca6 100644 --- a/v2/api/dbformysql/v1api20230630/storage/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20230630/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -300,6 +301,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) @@ -312,6 +324,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -680,6 +703,50 @@ func (in *FlexibleServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopyInto(out *FlexibleServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersAdministratorOperatorSpec. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopy() *FlexibleServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersAdministrator_STATUS) DeepCopyInto(out *FlexibleServersAdministrator_STATUS) { *out = *in @@ -772,6 +839,11 @@ func (in *FlexibleServersAdministrator_Spec) DeepCopyInto(out *FlexibleServersAd *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -875,6 +947,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -987,6 +1103,11 @@ func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersCo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1080,6 +1201,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -1152,6 +1317,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1235,6 +1405,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1302,6 +1516,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbformysql/v1api20230630/structure.txt b/v2/api/dbformysql/v1api20230630/structure.txt index 640f47c9ef7..2eccc871746 100644 --- a/v2/api/dbformysql/v1api20230630/structure.txt +++ b/v2/api/dbformysql/v1api20230630/structure.txt @@ -57,10 +57,12 @@ FlexibleServer: Resource │ │ └── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── AdministratorLogin: *genruntime.ConfigMapDestination │ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -211,11 +213,14 @@ FlexibleServer: Resource └── "8.0.21" FlexibleServersAdministrator: Resource ├── Owner: FlexibleServer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AdministratorType: *Enum (1 value) │ │ └── "ActiveDirectory" │ ├── IdentityResourceReference: *genruntime.ResourceReference │ ├── Login: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sid: *string │ ├── SidFromConfig: *genruntime.ConfigMapReference @@ -249,9 +254,12 @@ FlexibleServersAdministrator: Resource └── Type: *string FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── CurrentValue: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *Enum (2 values) │ │ ├── "system-default" @@ -298,10 +306,13 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -327,10 +338,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbformysql/v1api20230630/zz_generated.deepcopy.go b/v2/api/dbformysql/v1api20230630/zz_generated.deepcopy.go index e1fbdf9da69..835ef4a7c6f 100644 --- a/v2/api/dbformysql/v1api20230630/zz_generated.deepcopy.go +++ b/v2/api/dbformysql/v1api20230630/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230630 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -258,11 +259,33 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -617,6 +640,43 @@ func (in *FlexibleServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopyInto(out *FlexibleServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersAdministratorOperatorSpec. +func (in *FlexibleServersAdministratorOperatorSpec) DeepCopy() *FlexibleServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersAdministrator_STATUS) DeepCopyInto(out *FlexibleServersAdministrator_STATUS) { *out = *in @@ -702,6 +762,11 @@ func (in *FlexibleServersAdministrator_Spec) DeepCopyInto(out *FlexibleServersAd *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -798,6 +863,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -903,6 +1005,11 @@ func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersCo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -989,6 +1096,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -1054,6 +1198,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1130,6 +1279,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1190,6 +1376,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/flexible_server_types_gen.go index f3e7e4c8cd1..1405bab8a31 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_server_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServer{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (server *FlexibleServer) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (server *FlexibleServer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,9 +256,20 @@ func (server *FlexibleServer) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return server.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(server, nil, server.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (server *FlexibleServer) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(server) @@ -256,13 +289,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1976,6 +2009,12 @@ func (backup *Backup_STATUS) AssignProperties_To_Backup_STATUS(destination *stor // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -1983,6 +2022,42 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -2004,6 +2079,42 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen.go index c256379fa71..50896678547 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -211,7 +234,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -332,6 +377,10 @@ type FlexibleServersConfiguration_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -387,6 +436,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge // Set property "AzureName": configuration.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -471,6 +522,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -497,6 +560,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -981,6 +1056,110 @@ var configurationProperties_DataType_STATUS_Values = map[string]ConfigurationPro "numeric": ConfigurationProperties_DataType_STATUS_Numeric, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen_test.go index faf287b7737..7f4bccb690e 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_configuration_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,6 +483,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -395,6 +495,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -404,3 +510,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen.go index c395524faa4..d67e8e18221 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -339,6 +384,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -406,6 +455,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -478,6 +529,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -760,6 +835,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen_test.go index 28d77377db6..ef65463c002 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_database_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen.go index bb12384b4ee..40c4538e314 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -338,6 +383,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -401,6 +450,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -484,6 +535,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -520,6 +583,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -784,6 +859,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen_test.go index f7f1a2318bb..f303d5e77a5 100644 --- a/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/flexible_servers_firewall_rule_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_server_types_gen.go index 7a4ac7b0ddc..96264616b06 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_server_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (server *FlexibleServer) ConvertTo(hub conversion.Hub) error { return server.AssignProperties_To_FlexibleServer(destination) } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServer{} // AzureName returns the Azure name of the resource @@ -1367,8 +1390,10 @@ func (backup *Backup_STATUS) AssignProperties_To_Backup_STATUS(destination *stor // Storage version of v1api20210601.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec @@ -1376,6 +1401,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { propertyBag.Add("ConfigMaps", *source.ConfigMaps) @@ -1383,6 +1426,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer propertyBag.Remove("ConfigMaps") } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -1420,6 +1481,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if propertyBag.Contains("ConfigMaps") { var configMap storage.FlexibleServerOperatorConfigMaps @@ -1433,6 +1512,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen.go index e79ec689b8a..b6394bdd1ca 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (configuration *FlexibleServersConfiguration) ConvertTo(hub conversion.Hub) return configuration.AssignProperties_To_FlexibleServersConfiguration(destination) } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -234,8 +257,9 @@ type augmentConversionForFlexibleServersConfiguration interface { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -305,6 +329,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // OriginalVersion configuration.OriginalVersion = source.OriginalVersion @@ -350,6 +386,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion @@ -662,6 +710,141 @@ type augmentConversionForFlexibleServersConfiguration_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersConfiguration_STATUS) error } +// Storage version of v1api20210601.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersConfigurationOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersConfigurationOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersConfigurationOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen_test.go index 0384ed33bcb..ede7ed82ff1 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_configuration_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -381,6 +478,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -390,6 +490,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -400,3 +506,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen.go index 3466f7b09f0..21ee2f0ee46 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (database *FlexibleServersDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_FlexibleServersDatabase(destination) } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForFlexibleServersDatabase interface { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -312,6 +336,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // OriginalVersion database.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion @@ -570,6 +618,141 @@ type augmentConversionForFlexibleServersDatabase_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersDatabase_STATUS) error } +// Storage version of v1api20210601.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersDatabaseOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen_test.go index df8c3da6e7f..624cfd53b85 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_database_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen.go index 2a502ad6040..bfb3b49f033 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *FlexibleServersFirewallRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_FlexibleServersFirewallRule(destination) } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -235,9 +258,10 @@ type augmentConversionForFlexibleServersFirewallRule interface { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -309,6 +333,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ // EndIpAddress rule.EndIpAddress = genruntime.ClonePointerToString(source.EndIpAddress) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -354,6 +390,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer // EndIpAddress destination.EndIpAddress = genruntime.ClonePointerToString(rule.EndIpAddress) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -570,6 +618,141 @@ type augmentConversionForFlexibleServersFirewallRule_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersFirewallRule_STATUS) error } +// Storage version of v1api20210601.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen_test.go index a1c3a74fd8c..2c9814fd3e2 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/structure.txt b/v2/api/dbforpostgresql/v1api20210601/storage/structure.txt index eedbb1d8de7..897c39ff2f5 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/structure.txt +++ b/v2/api/dbforpostgresql/v1api20210601/storage/structure.txt @@ -30,8 +30,10 @@ FlexibleServer: Resource │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ ├── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -104,8 +106,12 @@ FlexibleServer: Resource └── Version: *string FlexibleServersConfiguration: Resource ├── Owner: dbforpostgresql/v1api20210601.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -138,10 +144,14 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: dbforpostgresql/v1api20210601.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -163,9 +173,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbforpostgresql/v1api20210601.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -194,12 +208,15 @@ augmentConversionForFlexibleServerOperatorSpec: Interface augmentConversionForFlexibleServer_STATUS: Interface augmentConversionForFlexibleServer_Spec: Interface augmentConversionForFlexibleServersConfiguration: Interface +augmentConversionForFlexibleServersConfigurationOperatorSpec: Interface augmentConversionForFlexibleServersConfiguration_STATUS: Interface augmentConversionForFlexibleServersConfiguration_Spec: Interface augmentConversionForFlexibleServersDatabase: Interface +augmentConversionForFlexibleServersDatabaseOperatorSpec: Interface augmentConversionForFlexibleServersDatabase_STATUS: Interface augmentConversionForFlexibleServersDatabase_Spec: Interface augmentConversionForFlexibleServersFirewallRule: Interface +augmentConversionForFlexibleServersFirewallRuleOperatorSpec: Interface augmentConversionForFlexibleServersFirewallRule_STATUS: Interface augmentConversionForFlexibleServersFirewallRule_Spec: Interface augmentConversionForHighAvailability: Interface diff --git a/v2/api/dbforpostgresql/v1api20210601/storage/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20210601/storage/zz_generated.deepcopy.go index c9463751d42..64d456c512f 100644 --- a/v2/api/dbforpostgresql/v1api20210601/storage/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20210601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -173,6 +174,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -180,6 +192,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -501,6 +524,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -608,6 +675,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -701,6 +773,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -773,6 +889,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -856,6 +977,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -923,6 +1088,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20210601/structure.txt b/v2/api/dbforpostgresql/v1api20210601/structure.txt index 93c02a71223..24a62ebbd5b 100644 --- a/v2/api/dbforpostgresql/v1api20210601/structure.txt +++ b/v2/api/dbforpostgresql/v1api20210601/structure.txt @@ -34,7 +34,9 @@ FlexibleServer: Resource │ ├── Network: *Object (2 properties) │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ └── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -139,8 +141,11 @@ FlexibleServer: Resource └── "14" FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *string │ └── Value: *string @@ -181,10 +186,13 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -210,10 +218,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbforpostgresql/v1api20210601/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20210601/zz_generated.deepcopy.go index b449ebff597..834f1eea1c5 100644 --- a/v2/api/dbforpostgresql/v1api20210601/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20210601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -152,6 +153,28 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -459,6 +482,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -559,6 +619,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -645,6 +710,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -710,6 +812,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -786,6 +893,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -846,6 +990,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_server_types_gen.go index c11da7f6c1f..375c32cac96 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_server_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -267,13 +288,13 @@ func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warning if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -295,13 +316,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2015,9 +2036,15 @@ func (backup *Backup_STATUS) AssignProperties_To_Backup_STATUS(destination *stor // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -2025,6 +2052,24 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -2037,6 +2082,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -2058,6 +2121,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -2070,6 +2151,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen.go index d221eec08aa..96e37c0dd48 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -211,7 +234,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -332,6 +377,10 @@ type FlexibleServersConfiguration_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -387,6 +436,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge // Set property "AzureName": configuration.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -471,6 +522,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -497,6 +560,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -981,6 +1056,110 @@ var configurationProperties_DataType_STATUS_Values = map[string]ConfigurationPro "numeric": ConfigurationProperties_DataType_STATUS_Numeric, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen_test.go index 21c590a1282..8283f7751b6 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_configuration_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220120ps.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,6 +483,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -395,6 +495,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -404,3 +510,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen.go index 0c19c6b5360..17279639ad6 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -339,6 +384,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -406,6 +455,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -478,6 +529,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -760,6 +835,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen_test.go index 39c95385bb0..47f63928cae 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_database_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220120ps.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen.go index 5b75ff7ac93..b3571b4bacd 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -338,6 +383,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -401,6 +450,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -484,6 +535,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -520,6 +583,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -784,6 +859,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen_test.go index b6173f8d36c..5b9a2954d47 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/flexible_servers_firewall_rule_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220120ps.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_server_types_gen.go index 8e93b7166dd..f137af15479 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_server_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -84,6 +86,26 @@ func (server *FlexibleServer) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -1223,9 +1245,11 @@ func (backup *Backup_STATUS) AssignProperties_To_Backup_STATUS(destination *v202 // Storage version of v1api20220120preview.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec @@ -1233,6 +1257,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if propertyBag.Contains("ConfigMaps") { var configMap FlexibleServerOperatorConfigMaps @@ -1246,6 +1288,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -1283,6 +1343,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { propertyBag.Add("ConfigMaps", *operator.ConfigMaps) @@ -1290,6 +1368,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp propertyBag.Remove("ConfigMaps") } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret v20210601s.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen.go index 2acfd70629a..e86da3ab056 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20210601/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (configuration *FlexibleServersConfiguration) ConvertTo(hub conversion.Hub) return nil } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -247,8 +270,9 @@ type augmentConversionForFlexibleServersConfiguration interface { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -318,6 +342,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // OriginalVersion configuration.OriginalVersion = source.OriginalVersion @@ -363,6 +399,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion @@ -675,6 +723,141 @@ type augmentConversionForFlexibleServersConfiguration_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersConfiguration_STATUS) error } +// Storage version of v1api20220120preview.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersConfigurationOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersConfigurationOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersConfigurationOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen_test.go index d3ade2db77b..d9daafb7a25 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_configuration_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -382,6 +479,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -391,6 +491,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -401,3 +507,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen.go index 372992f0aba..cfd330a8c8c 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20210601/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (database *FlexibleServersDatabase) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -248,10 +271,11 @@ type augmentConversionForFlexibleServersDatabase interface { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -325,6 +349,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // OriginalVersion database.OriginalVersion = source.OriginalVersion @@ -370,6 +406,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion @@ -583,6 +631,141 @@ type augmentConversionForFlexibleServersDatabase_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersDatabase_STATUS) error } +// Storage version of v1api20220120preview.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersDatabaseOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen_test.go index 7added11cac..6e677ff692a 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_database_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -392,3 +498,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen.go index 6c2f9ced8d9..35f132596cb 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20210601/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (rule *FlexibleServersFirewallRule) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -248,9 +271,10 @@ type augmentConversionForFlexibleServersFirewallRule interface { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -322,6 +346,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ // EndIpAddress rule.EndIpAddress = genruntime.ClonePointerToString(source.EndIpAddress) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -367,6 +403,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer // EndIpAddress destination.EndIpAddress = genruntime.ClonePointerToString(rule.EndIpAddress) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -583,6 +631,141 @@ type augmentConversionForFlexibleServersFirewallRule_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersFirewallRule_STATUS) error } +// Storage version of v1api20220120preview.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen_test.go index fd08b8f07b1..f2d4c54a262 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210601s.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -392,3 +498,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/structure.txt b/v2/api/dbforpostgresql/v1api20220120preview/storage/structure.txt index bda753b1a9f..fcb44af0570 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/structure.txt +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/structure.txt @@ -30,11 +30,13 @@ FlexibleServer: Resource │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ ├── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -107,8 +109,12 @@ FlexibleServer: Resource └── Version: *string FlexibleServersConfiguration: Resource ├── Owner: dbforpostgresql/v1api20220120preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -141,10 +147,14 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: dbforpostgresql/v1api20220120preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -166,9 +176,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbforpostgresql/v1api20220120preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -198,12 +212,15 @@ augmentConversionForFlexibleServerOperatorSpec: Interface augmentConversionForFlexibleServer_STATUS: Interface augmentConversionForFlexibleServer_Spec: Interface augmentConversionForFlexibleServersConfiguration: Interface +augmentConversionForFlexibleServersConfigurationOperatorSpec: Interface augmentConversionForFlexibleServersConfiguration_STATUS: Interface augmentConversionForFlexibleServersConfiguration_Spec: Interface augmentConversionForFlexibleServersDatabase: Interface +augmentConversionForFlexibleServersDatabaseOperatorSpec: Interface augmentConversionForFlexibleServersDatabase_STATUS: Interface augmentConversionForFlexibleServersDatabase_Spec: Interface augmentConversionForFlexibleServersFirewallRule: Interface +augmentConversionForFlexibleServersFirewallRuleOperatorSpec: Interface augmentConversionForFlexibleServersFirewallRule_STATUS: Interface augmentConversionForFlexibleServersFirewallRule_Spec: Interface augmentConversionForHighAvailability: Interface diff --git a/v2/api/dbforpostgresql/v1api20220120preview/storage/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20220120preview/storage/zz_generated.deepcopy.go index 050a430086e..306905c9cf6 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/storage/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -200,6 +201,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) @@ -212,6 +224,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -533,6 +556,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -640,6 +707,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -733,6 +805,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -805,6 +921,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -888,6 +1009,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -955,6 +1120,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20220120preview/structure.txt b/v2/api/dbforpostgresql/v1api20220120preview/structure.txt index 3d2d5a81446..8b1bec16eca 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/structure.txt +++ b/v2/api/dbforpostgresql/v1api20220120preview/structure.txt @@ -35,9 +35,11 @@ FlexibleServer: Resource │ ├── Network: *Object (2 properties) │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ └── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -143,8 +145,11 @@ FlexibleServer: Resource └── "14" FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *string │ └── Value: *string @@ -185,10 +190,13 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -214,10 +222,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbforpostgresql/v1api20220120preview/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20220120preview/zz_generated.deepcopy.go index c09af8a5ed4..f33bdf329d6 100644 --- a/v2/api/dbforpostgresql/v1api20220120preview/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20220120preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220120preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -172,11 +173,33 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -484,6 +507,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -584,6 +644,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -670,6 +735,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -735,6 +837,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -811,6 +918,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -871,6 +1015,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/flexible_server_types_gen.go index 9309e92f051..8582a01c1f1 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_server_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -97,6 +98,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServer{} // InitializeSpec initializes the spec for this resource from the given status @@ -267,13 +288,13 @@ func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warning if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set @@ -304,13 +325,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -3151,9 +3172,15 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -3161,6 +3188,24 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -3173,6 +3218,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -3194,6 +3257,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -3206,6 +3287,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen.go index a68db6dfeb0..a1d6ac4e961 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersConfiguration{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -226,7 +249,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -243,6 +280,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -331,6 +376,10 @@ type FlexibleServersConfiguration_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge // Set property "AzureName": configuration.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -470,6 +521,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -496,6 +559,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -993,6 +1068,110 @@ var configurationProperties_DataType_STATUS_Values = map[string]ConfigurationPro "numeric": ConfigurationProperties_DataType_STATUS_Numeric, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen_test.go index 89c4559076a..350d75e5c93 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_configuration_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,6 +482,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -394,6 +494,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -403,3 +509,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen.go index 9021a4adae7..7db27ef5afb 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -340,6 +385,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -407,6 +456,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -489,6 +540,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ database.Collation = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -525,6 +588,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer destination.Collation = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -804,6 +879,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen_test.go index a0c3a7f2da4..775ac7a8317 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_database_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -390,3 +496,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen.go index dac8c9c63da..202f09dc849 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FlexibleServersFirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -337,6 +382,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -400,6 +449,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -483,6 +534,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -519,6 +582,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -806,6 +881,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen_test.go index d9c32bdc85f..1c598783aec 100644 --- a/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/flexible_servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -390,3 +496,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_server_types_gen.go index ff36036916b..21060ebdf43 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_server_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (server *FlexibleServer) SetConditions(conditions conditions.Conditions) { server.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -337,9 +359,11 @@ type DataEncryption_STATUS struct { // Storage version of v1api20221201.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20221201.HighAvailability diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen.go index 4d9d4179b5a..38c92913fae 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (configuration *FlexibleServersConfiguration) SetConditions(conditions cond configuration.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -141,8 +164,9 @@ type FlexibleServersConfigurationList struct { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -215,6 +239,14 @@ func (configuration *FlexibleServersConfiguration_STATUS) ConvertStatusTo(destin return destination.ConvertStatusFrom(configuration) } +// Storage version of v1api20221201.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen_test.go index 4d22612da79..9ebe771dafc 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_configuration_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -211,6 +266,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -220,6 +278,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -230,3 +294,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen.go index 4d3d25d09c7..b8f53ad66aa 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *FlexibleServersDatabase) SetConditions(conditions conditions.Con database.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type FlexibleServersDatabaseList struct { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -207,6 +231,14 @@ func (database *FlexibleServersDatabase_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(database) } +// Storage version of v1api20221201.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen_test.go index 3f82bf2fff1..ef0e4494757 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_database_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -211,6 +269,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen.go index d93c8d795dc..4297b5db207 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *FlexibleServersFirewallRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type FlexibleServersFirewallRuleList struct { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -207,6 +231,14 @@ func (rule *FlexibleServersFirewallRule_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20221201.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen_test.go index 5a71143375c..6130a5e3640 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -211,6 +269,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/structure.txt b/v2/api/dbforpostgresql/v1api20221201/storage/structure.txt index da26d918acf..572d02f32db 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/structure.txt +++ b/v2/api/dbforpostgresql/v1api20221201/storage/structure.txt @@ -47,11 +47,13 @@ FlexibleServer: Resource │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ ├── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -145,8 +147,12 @@ FlexibleServer: Resource └── Version: *string FlexibleServersConfiguration: Resource ├── Owner: dbforpostgresql/v1api20221201.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -179,10 +185,14 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: dbforpostgresql/v1api20221201.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -204,9 +214,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbforpostgresql/v1api20221201.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/dbforpostgresql/v1api20221201/storage/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20221201/storage/zz_generated.deepcopy.go index 3efc6aad7ad..cae1f27f381 100644 --- a/v2/api/dbforpostgresql/v1api20221201/storage/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20221201/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -353,6 +354,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) @@ -365,6 +377,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -731,6 +754,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -838,6 +905,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -931,6 +1003,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -1003,6 +1119,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1086,6 +1207,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1153,6 +1318,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20221201/structure.txt b/v2/api/dbforpostgresql/v1api20221201/structure.txt index 97acb28cc11..a2db6dace2e 100644 --- a/v2/api/dbforpostgresql/v1api20221201/structure.txt +++ b/v2/api/dbforpostgresql/v1api20221201/structure.txt @@ -61,9 +61,11 @@ FlexibleServer: Resource │ ├── Network: *Object (2 properties) │ │ ├── DelegatedSubnetResourceReference: *genruntime.ResourceReference │ │ └── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -204,10 +206,13 @@ FlexibleServer: Resource └── "14" FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *string │ └── Value: *string @@ -248,7 +253,7 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" @@ -256,6 +261,9 @@ FlexibleServersDatabase: Resource │ │ └── Rule 0: Pattern: "^[a-zA-Z]+\\w*$" │ ├── Collation: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z\\-]+([. ]|\\w)*$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -281,12 +289,15 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbforpostgresql/v1api20221201/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20221201/zz_generated.deepcopy.go index 131598c129d..e5518d17f6b 100644 --- a/v2/api/dbforpostgresql/v1api20221201/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20221201/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20221201 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -297,11 +298,33 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -654,6 +677,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -754,6 +814,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -840,6 +905,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -905,6 +1007,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -981,6 +1088,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1041,6 +1185,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_server_types_gen.go index dee845d03ff..b6dbab709dd 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_server_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (server *FlexibleServer) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServer resource func (server *FlexibleServer) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -270,13 +291,13 @@ func (server *FlexibleServer) validateConfigMapDestinations() (admission.Warning if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set @@ -307,13 +328,13 @@ func (server *FlexibleServer) validateSecretDestinations() (admission.Warnings, if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + var toValidate []*genruntime.SecretDestination + if server.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + server.Spec.OperatorSpec.Secrets.FullyQualifiedDomainName, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -3308,9 +3329,15 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } @@ -3318,6 +3345,24 @@ type FlexibleServerOperatorSpec struct { // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServerOperatorSpec(source *storage.FlexibleServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -3330,6 +3375,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -3351,6 +3414,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -3363,6 +3444,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen.go index b42e0580f7c..ad8b5c62962 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (configuration *FlexibleServersConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersConfiguration resource func (configuration *FlexibleServersConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -211,7 +234,7 @@ func (configuration *FlexibleServersConfiguration) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (configuration *FlexibleServersConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOwnerReference, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -229,7 +252,21 @@ func (configuration *FlexibleServersConfiguration) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FlexibleServersConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -246,6 +283,14 @@ func (configuration *FlexibleServersConfiguration) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FlexibleServersConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FlexibleServersConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersConfiguration) @@ -334,6 +379,10 @@ type FlexibleServersConfiguration_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -389,6 +438,8 @@ func (configuration *FlexibleServersConfiguration_Spec) PopulateFromARM(owner ge // Set property "AzureName": configuration.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -473,6 +524,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -499,6 +562,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -983,6 +1058,110 @@ var configurationProperties_DataType_STATUS_Values = map[string]ConfigurationPro "numeric": ConfigurationProperties_DataType_STATUS_Numeric, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen_test.go index 4457688cdf6..af60556bac8 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_configuration_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230601ps.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,6 +483,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -395,6 +495,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -404,3 +510,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen.go index d855687f5ec..dde542e6a96 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *FlexibleServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersDatabase resource func (database *FlexibleServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *FlexibleServersDatabase) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (database *FlexibleServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *FlexibleServersDatabase) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *FlexibleServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *FlexibleServersDatabase) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *FlexibleServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *FlexibleServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersDatabase) @@ -343,6 +388,10 @@ type FlexibleServersDatabase_Spec struct { // Collation: The collation of the database. Collation *string `json:"collation,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -410,6 +459,8 @@ func (database *FlexibleServersDatabase_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -492,6 +543,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ database.Collation = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -528,6 +591,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer destination.Collation = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -784,6 +859,110 @@ func (database *FlexibleServersDatabase_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen_test.go index fb958766102..ad5d0438518 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_database_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230601ps.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Charset"] = gen.PtrOf(gen.AlphaString()) gens["Collation"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen.go index 20d62060dc1..d1b2ef5dce7 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *FlexibleServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the FlexibleServersFirewallRule resource func (rule *FlexibleServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *FlexibleServersFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *FlexibleServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *FlexibleServersFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *FlexibleServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *FlexibleServersFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *FlexibleServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *FlexibleServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FlexibleServersFirewallRule) @@ -340,6 +385,10 @@ type FlexibleServersFirewallRule_Spec struct { // EndIpAddress: The end IP address of the server firewall rule. Must be IPv4 format. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -403,6 +452,8 @@ func (rule *FlexibleServersFirewallRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -486,6 +537,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ rule.EndIpAddress = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -522,6 +585,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer destination.EndIpAddress = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -786,6 +861,110 @@ func (rule *FlexibleServersFirewallRule_STATUS) AssignProperties_To_FlexibleServ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen_test.go index cd70547ca48..5dd740403df 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/flexible_servers_firewall_rule_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20230601ps.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -382,6 +482,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_server_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_server_types_gen.go index 13ed49e93fe..251143f2ad4 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_server_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_server_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -70,6 +72,26 @@ func (server *FlexibleServer) ConvertTo(hub conversion.Hub) error { return server.AssignProperties_To_FlexibleServer(destination) } +var _ configmaps.Exporter = &FlexibleServer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *FlexibleServer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *FlexibleServer) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &FlexibleServer{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -1973,9 +1995,11 @@ func (encryption *DataEncryption_STATUS) AssignProperties_To_DataEncryption_STAT // Storage version of v1api20230601preview.FlexibleServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type FlexibleServerOperatorSpec struct { - ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *FlexibleServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *FlexibleServerOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_FlexibleServerOperatorSpec populates our FlexibleServerOperatorSpec from the provided source FlexibleServerOperatorSpec @@ -1983,6 +2007,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap FlexibleServerOperatorConfigMaps @@ -1995,6 +2037,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_From_FlexibleServer operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret FlexibleServerOperatorSecrets @@ -2032,6 +2092,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.FlexibleServerOperatorConfigMaps @@ -2044,6 +2122,24 @@ func (operator *FlexibleServerOperatorSpec) AssignProperties_To_FlexibleServerOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.FlexibleServerOperatorSecrets diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen.go index 8ab6905ce3c..a5e6c19841b 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (configuration *FlexibleServersConfiguration) ConvertTo(hub conversion.Hub) return configuration.AssignProperties_To_FlexibleServersConfiguration(destination) } +var _ configmaps.Exporter = &FlexibleServersConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FlexibleServersConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FlexibleServersConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersConfiguration{} // AzureName returns the Azure name of the resource @@ -234,8 +257,9 @@ type augmentConversionForFlexibleServersConfiguration interface { type FlexibleServersConfiguration_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *FlexibleServersConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -305,6 +329,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_From_Fl // AzureName configuration.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // OriginalVersion configuration.OriginalVersion = source.OriginalVersion @@ -350,6 +386,18 @@ func (configuration *FlexibleServersConfiguration_Spec) AssignProperties_To_Flex // AzureName destination.AzureName = configuration.AzureName + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion @@ -662,6 +710,141 @@ type augmentConversionForFlexibleServersConfiguration_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersConfiguration_STATUS) error } +// Storage version of v1api20230601preview.FlexibleServersConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersConfigurationOperatorSpec populates our FlexibleServersConfigurationOperatorSpec from the provided source FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_From_FlexibleServersConfigurationOperatorSpec(source *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersConfigurationOperatorSpec populates the provided destination FlexibleServersConfigurationOperatorSpec from our FlexibleServersConfigurationOperatorSpec +func (operator *FlexibleServersConfigurationOperatorSpec) AssignProperties_To_FlexibleServersConfigurationOperatorSpec(destination *storage.FlexibleServersConfigurationOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersConfigurationOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersConfigurationOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersConfigurationOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersConfigurationOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersConfigurationOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersConfiguration{}, &FlexibleServersConfigurationList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen_test.go index 0384ed33bcb..ede7ed82ff1 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_configuration_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration(gens map[string gens["Status"] = FlexibleServersConfiguration_STATUSGenerator() } +func Test_FlexibleServersConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersConfigurationOperatorSpec to FlexibleServersConfigurationOperatorSpec via AssignProperties_To_FlexibleServersConfigurationOperatorSpec & AssignProperties_From_FlexibleServersConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec tests if a specific instance of FlexibleServersConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersConfigurationOperatorSpec + err := copied.AssignProperties_To_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersConfigurationOperatorSpec + err = actual.AssignProperties_From_FlexibleServersConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec, FlexibleServersConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec runs a test to see if a specific instance of FlexibleServersConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersConfigurationOperatorSpec(subject FlexibleServersConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersConfigurationOperatorSpecGenerator() +var flexibleServersConfigurationOperatorSpecGenerator gopter.Gen + +// FlexibleServersConfigurationOperatorSpecGenerator returns a generator of FlexibleServersConfigurationOperatorSpec instances for property testing. +func FlexibleServersConfigurationOperatorSpecGenerator() gopter.Gen { + if flexibleServersConfigurationOperatorSpecGenerator != nil { + return flexibleServersConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfigurationOperatorSpec{}), generators) + + return flexibleServersConfigurationOperatorSpecGenerator +} + func Test_FlexibleServersConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -381,6 +478,9 @@ func RunJSONSerializationTestForFlexibleServersConfiguration_Spec(subject Flexib var flexibleServersConfiguration_SpecGenerator gopter.Gen // FlexibleServersConfiguration_SpecGenerator returns a generator of FlexibleServersConfiguration_Spec instances for property testing. +// We first initialize flexibleServersConfiguration_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { if flexibleServersConfiguration_SpecGenerator != nil { return flexibleServersConfiguration_SpecGenerator @@ -390,6 +490,12 @@ func FlexibleServersConfiguration_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(generators) + flexibleServersConfiguration_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersConfiguration_Spec{}), generators) + return flexibleServersConfiguration_SpecGenerator } @@ -400,3 +506,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens m gens["Source"] = gen.PtrOf(gen.AlphaString()) gens["Value"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersConfiguration_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersConfigurationOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen.go index 412973f5cad..73d913868e6 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (database *FlexibleServersDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_FlexibleServersDatabase(destination) } +var _ configmaps.Exporter = &FlexibleServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *FlexibleServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *FlexibleServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersDatabase{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForFlexibleServersDatabase interface { type FlexibleServersDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Charset *string `json:"charset,omitempty"` - Collation *string `json:"collation,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Charset *string `json:"charset,omitempty"` + Collation *string `json:"collation,omitempty"` + OperatorSpec *FlexibleServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -312,6 +336,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_From_FlexibleServ // Collation database.Collation = genruntime.ClonePointerToString(source.Collation) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // OriginalVersion database.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (database *FlexibleServersDatabase_Spec) AssignProperties_To_FlexibleServer // Collation destination.Collation = genruntime.ClonePointerToString(database.Collation) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion @@ -570,6 +618,141 @@ type augmentConversionForFlexibleServersDatabase_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersDatabase_STATUS) error } +// Storage version of v1api20230601preview.FlexibleServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersDatabaseOperatorSpec populates our FlexibleServersDatabaseOperatorSpec from the provided source FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_From_FlexibleServersDatabaseOperatorSpec(source *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersDatabaseOperatorSpec populates the provided destination FlexibleServersDatabaseOperatorSpec from our FlexibleServersDatabaseOperatorSpec +func (operator *FlexibleServersDatabaseOperatorSpec) AssignProperties_To_FlexibleServersDatabaseOperatorSpec(destination *storage.FlexibleServersDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersDatabaseOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersDatabase{}, &FlexibleServersDatabaseList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen_test.go index df8c3da6e7f..624cfd53b85 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_database_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersDatabase(gens map[string]gopt gens["Status"] = FlexibleServersDatabase_STATUSGenerator() } +func Test_FlexibleServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersDatabaseOperatorSpec to FlexibleServersDatabaseOperatorSpec via AssignProperties_To_FlexibleServersDatabaseOperatorSpec & AssignProperties_From_FlexibleServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec tests if a specific instance of FlexibleServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersDatabaseOperatorSpec + err := copied.AssignProperties_To_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersDatabaseOperatorSpec + err = actual.AssignProperties_From_FlexibleServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec, FlexibleServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec runs a test to see if a specific instance of FlexibleServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersDatabaseOperatorSpec(subject FlexibleServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersDatabaseOperatorSpecGenerator() +var flexibleServersDatabaseOperatorSpecGenerator gopter.Gen + +// FlexibleServersDatabaseOperatorSpecGenerator returns a generator of FlexibleServersDatabaseOperatorSpec instances for property testing. +func FlexibleServersDatabaseOperatorSpecGenerator() gopter.Gen { + if flexibleServersDatabaseOperatorSpecGenerator != nil { + return flexibleServersDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabaseOperatorSpec{}), generators) + + return flexibleServersDatabaseOperatorSpecGenerator +} + func Test_FlexibleServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersDatabase_Spec(subject FlexibleSer var flexibleServersDatabase_SpecGenerator gopter.Gen // FlexibleServersDatabase_SpecGenerator returns a generator of FlexibleServersDatabase_Spec instances for property testing. +// We first initialize flexibleServersDatabase_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersDatabase_SpecGenerator() gopter.Gen { if flexibleServersDatabase_SpecGenerator != nil { return flexibleServersDatabase_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersDatabase_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(generators) + flexibleServersDatabase_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersDatabase_Spec{}), generators) + return flexibleServersDatabase_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[st gens["Collation"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersDatabaseOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen.go index af268176429..bb32e94ce07 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/dbforpostgresql/v1api20221201/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *FlexibleServersFirewallRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_FlexibleServersFirewallRule(destination) } +var _ configmaps.Exporter = &FlexibleServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *FlexibleServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FlexibleServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *FlexibleServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FlexibleServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -235,9 +258,10 @@ type augmentConversionForFlexibleServersFirewallRule interface { type FlexibleServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *FlexibleServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -309,6 +333,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_From_FlexibleServ // EndIpAddress rule.EndIpAddress = genruntime.ClonePointerToString(source.EndIpAddress) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FlexibleServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -354,6 +390,18 @@ func (rule *FlexibleServersFirewallRule_Spec) AssignProperties_To_FlexibleServer // EndIpAddress destination.EndIpAddress = genruntime.ClonePointerToString(rule.EndIpAddress) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.FlexibleServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -570,6 +618,141 @@ type augmentConversionForFlexibleServersFirewallRule_STATUS interface { AssignPropertiesTo(dst *storage.FlexibleServersFirewallRule_STATUS) error } +// Storage version of v1api20230601preview.FlexibleServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FlexibleServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec populates our FlexibleServersFirewallRuleOperatorSpec from the provided source FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(source *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec populates the provided destination FlexibleServersFirewallRuleOperatorSpec from our FlexibleServersFirewallRuleOperatorSpec +func (operator *FlexibleServersFirewallRuleOperatorSpec) AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(destination *storage.FlexibleServersFirewallRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFlexibleServersFirewallRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFlexibleServersFirewallRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.FlexibleServersFirewallRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.FlexibleServersFirewallRuleOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FlexibleServersFirewallRule{}, &FlexibleServersFirewallRuleList{}) } diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen_test.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen_test.go index a1c3a74fd8c..2c9814fd3e2 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen_test.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/flexible_servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule(gens map[string] gens["Status"] = FlexibleServersFirewallRule_STATUSGenerator() } +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FlexibleServersFirewallRuleOperatorSpec to FlexibleServersFirewallRuleOperatorSpec via AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec & AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec tests if a specific instance of FlexibleServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FlexibleServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FlexibleServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_FlexibleServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FlexibleServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FlexibleServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec, FlexibleServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec runs a test to see if a specific instance of FlexibleServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFlexibleServersFirewallRuleOperatorSpec(subject FlexibleServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FlexibleServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// FlexibleServersFirewallRuleOperatorSpecGenerator() +var flexibleServersFirewallRuleOperatorSpecGenerator gopter.Gen + +// FlexibleServersFirewallRuleOperatorSpecGenerator returns a generator of FlexibleServersFirewallRuleOperatorSpec instances for property testing. +func FlexibleServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if flexibleServersFirewallRuleOperatorSpecGenerator != nil { + return flexibleServersFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + flexibleServersFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRuleOperatorSpec{}), generators) + + return flexibleServersFirewallRuleOperatorSpecGenerator +} + func Test_FlexibleServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForFlexibleServersFirewallRule_Spec(subject Flexibl var flexibleServersFirewallRule_SpecGenerator gopter.Gen // FlexibleServersFirewallRule_SpecGenerator returns a generator of FlexibleServersFirewallRule_Spec instances for property testing. +// We first initialize flexibleServersFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { if flexibleServersFirewallRule_SpecGenerator != nil { return flexibleServersFirewallRule_SpecGenerator @@ -381,6 +481,12 @@ func FlexibleServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(generators) + flexibleServersFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(FlexibleServersFirewallRule_Spec{}), generators) + return flexibleServersFirewallRule_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFlexibleServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FlexibleServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/structure.txt b/v2/api/dbforpostgresql/v1api20230601preview/storage/structure.txt index 14c42d6376b..16a338c3feb 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/structure.txt +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/structure.txt @@ -53,11 +53,13 @@ FlexibleServer: Resource │ │ ├── PrivateDnsZoneArmResourceReference: *genruntime.ResourceReference │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── PublicNetworkAccess: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── FullyQualifiedDomainName: *genruntime.SecretDestination │ │ └── PropertyBag: genruntime.PropertyBag @@ -180,8 +182,12 @@ FlexibleServer: Resource └── Version: *string FlexibleServersConfiguration: Resource ├── Owner: dbforpostgresql/v1api20230601preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -214,10 +220,14 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: dbforpostgresql/v1api20230601preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Charset: *string │ ├── Collation: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -239,9 +249,13 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: dbforpostgresql/v1api20230601preview.FlexibleServer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -275,12 +289,15 @@ augmentConversionForFlexibleServerOperatorSpec: Interface augmentConversionForFlexibleServer_STATUS: Interface augmentConversionForFlexibleServer_Spec: Interface augmentConversionForFlexibleServersConfiguration: Interface +augmentConversionForFlexibleServersConfigurationOperatorSpec: Interface augmentConversionForFlexibleServersConfiguration_STATUS: Interface augmentConversionForFlexibleServersConfiguration_Spec: Interface augmentConversionForFlexibleServersDatabase: Interface +augmentConversionForFlexibleServersDatabaseOperatorSpec: Interface augmentConversionForFlexibleServersDatabase_STATUS: Interface augmentConversionForFlexibleServersDatabase_Spec: Interface augmentConversionForFlexibleServersFirewallRule: Interface +augmentConversionForFlexibleServersFirewallRuleOperatorSpec: Interface augmentConversionForFlexibleServersFirewallRule_STATUS: Interface augmentConversionForFlexibleServersFirewallRule_Spec: Interface augmentConversionForHighAvailability: Interface diff --git a/v2/api/dbforpostgresql/v1api20230601preview/storage/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20230601preview/storage/zz_generated.deepcopy.go index 18771887618..197f609b15f 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/storage/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -398,6 +399,17 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) @@ -410,6 +422,17 @@ func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -793,6 +816,50 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -900,6 +967,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -993,6 +1065,50 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -1065,6 +1181,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1148,6 +1269,50 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1215,6 +1380,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/dbforpostgresql/v1api20230601preview/structure.txt b/v2/api/dbforpostgresql/v1api20230601preview/structure.txt index 9e1cda06bbb..2586cd693e9 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/structure.txt +++ b/v2/api/dbforpostgresql/v1api20230601preview/structure.txt @@ -74,9 +74,11 @@ FlexibleServer: Resource │ │ └── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (1 property) │ │ └── FullyQualifiedDomainName: *genruntime.SecretDestination │ ├── Owner: *genruntime.KnownResourceReference @@ -310,10 +312,13 @@ FlexibleServer: Resource └── "16" FlexibleServersConfiguration: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Source: *string │ └── Value: *string @@ -354,7 +359,7 @@ FlexibleServersConfiguration: Resource └── Value: *string FlexibleServersDatabase: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" @@ -362,6 +367,9 @@ FlexibleServersDatabase: Resource │ │ └── Rule 0: Pattern: "^[a-zA-Z]+\\w*$" │ ├── Collation: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z\\-]+([. ]|\\w)*$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Charset: *string @@ -387,12 +395,15 @@ FlexibleServersDatabase: Resource └── Type: *string FlexibleServersFirewallRule: Resource ├── Owner: FlexibleServer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MinLength: 1 │ │ └── Rule 1: Pattern: "^[-\\w\\._]+$" │ ├── EndIpAddress: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: Validated<*string> (1 rule) │ └── Rule 0: Pattern: "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" diff --git a/v2/api/dbforpostgresql/v1api20230601preview/zz_generated.deepcopy.go b/v2/api/dbforpostgresql/v1api20230601preview/zz_generated.deepcopy.go index 232f6409693..65735c2bb02 100644 --- a/v2/api/dbforpostgresql/v1api20230601preview/zz_generated.deepcopy.go +++ b/v2/api/dbforpostgresql/v1api20230601preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230601preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -342,11 +343,33 @@ func (in *FlexibleServerOperatorSecrets) DeepCopy() *FlexibleServerOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServerOperatorSpec) DeepCopyInto(out *FlexibleServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(FlexibleServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(FlexibleServerOperatorSecrets) @@ -716,6 +739,43 @@ func (in *FlexibleServersConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopyInto(out *FlexibleServersConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersConfigurationOperatorSpec. +func (in *FlexibleServersConfigurationOperatorSpec) DeepCopy() *FlexibleServersConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_STATUS) DeepCopyInto(out *FlexibleServersConfiguration_STATUS) { *out = *in @@ -816,6 +876,11 @@ func (in *FlexibleServersConfiguration_STATUS) DeepCopy() *FlexibleServersConfig // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersConfiguration_Spec) DeepCopyInto(out *FlexibleServersConfiguration_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -902,6 +967,43 @@ func (in *FlexibleServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopyInto(out *FlexibleServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersDatabaseOperatorSpec. +func (in *FlexibleServersDatabaseOperatorSpec) DeepCopy() *FlexibleServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersDatabase_STATUS) DeepCopyInto(out *FlexibleServersDatabase_STATUS) { *out = *in @@ -967,6 +1069,11 @@ func (in *FlexibleServersDatabase_Spec) DeepCopyInto(out *FlexibleServersDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1043,6 +1150,43 @@ func (in *FlexibleServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopyInto(out *FlexibleServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlexibleServersFirewallRuleOperatorSpec. +func (in *FlexibleServersFirewallRuleOperatorSpec) DeepCopy() *FlexibleServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(FlexibleServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FlexibleServersFirewallRule_STATUS) DeepCopyInto(out *FlexibleServersFirewallRule_STATUS) { *out = *in @@ -1103,6 +1247,11 @@ func (in *FlexibleServersFirewallRule_Spec) DeepCopyInto(out *FlexibleServersFir *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FlexibleServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/devices/v1api20210702/iot_hub_types_gen.go b/v2/api/devices/v1api20210702/iot_hub_types_gen.go index e44c1e7256a..1eae70bfe3c 100644 --- a/v2/api/devices/v1api20210702/iot_hub_types_gen.go +++ b/v2/api/devices/v1api20210702/iot_hub_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (iotHub *IotHub) defaultAzureName() { // defaultImpl applies the code generated defaults to the IotHub resource func (iotHub *IotHub) defaultImpl() { iotHub.defaultAzureName() } +var _ configmaps.Exporter = &IotHub{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (iotHub *IotHub) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if iotHub.Spec.OperatorSpec == nil { + return nil + } + return iotHub.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &IotHub{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (iotHub *IotHub) SecretDestinationExpressions() []*core.DestinationExpression { + if iotHub.Spec.OperatorSpec == nil { + return nil + } + return iotHub.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &IotHub{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (iotHub *IotHub) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (iotHub *IotHub) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){iotHub.validateResourceReferences, iotHub.validateOwnerReference, iotHub.validateSecretDestinations} + return []func() (admission.Warnings, error){iotHub.validateResourceReferences, iotHub.validateOwnerReference, iotHub.validateSecretDestinations, iotHub.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (iotHub *IotHub) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return iotHub.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return iotHub.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (iotHub *IotHub) validateConfigMapDestinations() (admission.Warnings, error) { + if iotHub.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(iotHub, nil, iotHub.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,22 +286,22 @@ func (iotHub *IotHub) validateSecretDestinations() (admission.Warnings, error) { if iotHub.Spec.OperatorSpec == nil { return nil, nil } - if iotHub.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - iotHub.Spec.OperatorSpec.Secrets.DevicePrimaryKey, - iotHub.Spec.OperatorSpec.Secrets.DeviceSecondaryKey, - iotHub.Spec.OperatorSpec.Secrets.IotHubOwnerPrimaryKey, - iotHub.Spec.OperatorSpec.Secrets.IotHubOwnerSecondaryKey, - iotHub.Spec.OperatorSpec.Secrets.RegistryReadPrimaryKey, - iotHub.Spec.OperatorSpec.Secrets.RegistryReadSecondaryKey, - iotHub.Spec.OperatorSpec.Secrets.RegistryReadWritePrimaryKey, - iotHub.Spec.OperatorSpec.Secrets.RegistryReadWriteSecondaryKey, - iotHub.Spec.OperatorSpec.Secrets.ServicePrimaryKey, - iotHub.Spec.OperatorSpec.Secrets.ServiceSecondaryKey, + var toValidate []*genruntime.SecretDestination + if iotHub.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + iotHub.Spec.OperatorSpec.Secrets.DevicePrimaryKey, + iotHub.Spec.OperatorSpec.Secrets.DeviceSecondaryKey, + iotHub.Spec.OperatorSpec.Secrets.IotHubOwnerPrimaryKey, + iotHub.Spec.OperatorSpec.Secrets.IotHubOwnerSecondaryKey, + iotHub.Spec.OperatorSpec.Secrets.RegistryReadPrimaryKey, + iotHub.Spec.OperatorSpec.Secrets.RegistryReadSecondaryKey, + iotHub.Spec.OperatorSpec.Secrets.RegistryReadWritePrimaryKey, + iotHub.Spec.OperatorSpec.Secrets.RegistryReadWriteSecondaryKey, + iotHub.Spec.OperatorSpec.Secrets.ServicePrimaryKey, + iotHub.Spec.OperatorSpec.Secrets.ServiceSecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(iotHub, toValidate, iotHub.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1454,6 +1487,12 @@ func (identity *ArmIdentity_STATUS) AssignProperties_To_ArmIdentity_STATUS(desti // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type IotHubOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *IotHubOperatorSecrets `json:"secrets,omitempty"` } @@ -1461,6 +1500,42 @@ type IotHubOperatorSpec struct { // AssignProperties_From_IotHubOperatorSpec populates our IotHubOperatorSpec from the provided source IotHubOperatorSpec func (operator *IotHubOperatorSpec) AssignProperties_From_IotHubOperatorSpec(source *storage.IotHubOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret IotHubOperatorSecrets @@ -1482,6 +1557,42 @@ func (operator *IotHubOperatorSpec) AssignProperties_To_IotHubOperatorSpec(desti // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.IotHubOperatorSecrets diff --git a/v2/api/devices/v1api20210702/storage/iot_hub_types_gen.go b/v2/api/devices/v1api20210702/storage/iot_hub_types_gen.go index d2d42d35c7d..670581bdf30 100644 --- a/v2/api/devices/v1api20210702/storage/iot_hub_types_gen.go +++ b/v2/api/devices/v1api20210702/storage/iot_hub_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (iotHub *IotHub) SetConditions(conditions conditions.Conditions) { iotHub.Status.Conditions = conditions } +var _ configmaps.Exporter = &IotHub{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (iotHub *IotHub) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if iotHub.Spec.OperatorSpec == nil { + return nil + } + return iotHub.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &IotHub{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (iotHub *IotHub) SecretDestinationExpressions() []*core.DestinationExpression { + if iotHub.Spec.OperatorSpec == nil { + return nil + } + return iotHub.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &IotHub{} // AzureName returns the Azure name of the resource @@ -240,8 +263,10 @@ type ArmIdentity_STATUS struct { // Storage version of v1api20210702.IotHubOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type IotHubOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *IotHubOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *IotHubOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20210702.IotHubProperties diff --git a/v2/api/devices/v1api20210702/storage/structure.txt b/v2/api/devices/v1api20210702/storage/structure.txt index 60bb5d944dc..8bf9a1f3578 100644 --- a/v2/api/devices/v1api20210702/storage/structure.txt +++ b/v2/api/devices/v1api20210702/storage/structure.txt @@ -14,8 +14,10 @@ IotHub: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (11 properties) │ │ ├── DevicePrimaryKey: *genruntime.SecretDestination │ │ ├── DeviceSecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/devices/v1api20210702/storage/zz_generated.deepcopy.go b/v2/api/devices/v1api20210702/storage/zz_generated.deepcopy.go index 8bd0ff99857..7d3c0edcec2 100644 --- a/v2/api/devices/v1api20210702/storage/zz_generated.deepcopy.go +++ b/v2/api/devices/v1api20210702/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -686,6 +687,17 @@ func (in *IotHubOperatorSecrets) DeepCopy() *IotHubOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IotHubOperatorSpec) DeepCopyInto(out *IotHubOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -693,6 +705,17 @@ func (in *IotHubOperatorSpec) DeepCopyInto(out *IotHubOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(IotHubOperatorSecrets) diff --git a/v2/api/devices/v1api20210702/structure.txt b/v2/api/devices/v1api20210702/structure.txt index 4bfa317bc7b..e5c8cdfa738 100644 --- a/v2/api/devices/v1api20210702/structure.txt +++ b/v2/api/devices/v1api20210702/structure.txt @@ -16,7 +16,9 @@ IotHub: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (10 properties) │ │ ├── DevicePrimaryKey: *genruntime.SecretDestination │ │ ├── DeviceSecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/devices/v1api20210702/zz_generated.deepcopy.go b/v2/api/devices/v1api20210702/zz_generated.deepcopy.go index dd382ee75ae..d6a36356a54 100644 --- a/v2/api/devices/v1api20210702/zz_generated.deepcopy.go +++ b/v2/api/devices/v1api20210702/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210702 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -579,6 +580,28 @@ func (in *IotHubOperatorSecrets) DeepCopy() *IotHubOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IotHubOperatorSpec) DeepCopyInto(out *IotHubOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(IotHubOperatorSecrets) diff --git a/v2/api/documentdb/v1api20210515/database_account_types_gen.go b/v2/api/documentdb/v1api20210515/database_account_types_gen.go index 383e4fbab2a..4aad530df1e 100644 --- a/v2/api/documentdb/v1api20210515/database_account_types_gen.go +++ b/v2/api/documentdb/v1api20210515/database_account_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (account *DatabaseAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the DatabaseAccount resource func (account *DatabaseAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &DatabaseAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *DatabaseAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DatabaseAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *DatabaseAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DatabaseAccount{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (account *DatabaseAccount) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (account *DatabaseAccount) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations} + return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations, account.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (account *DatabaseAccount) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return account.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (account *DatabaseAccount) validateConfigMapDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(account, nil, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,17 +289,17 @@ func (account *DatabaseAccount) validateSecretDestinations() (admission.Warnings if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - account.Spec.OperatorSpec.Secrets.DocumentEndpoint, - account.Spec.OperatorSpec.Secrets.PrimaryMasterKey, - account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, - account.Spec.OperatorSpec.Secrets.SecondaryMasterKey, - account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, + var toValidate []*genruntime.SecretDestination + if account.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + account.Spec.OperatorSpec.Secrets.DocumentEndpoint, + account.Spec.OperatorSpec.Secrets.PrimaryMasterKey, + account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, + account.Spec.OperatorSpec.Secrets.SecondaryMasterKey, + account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -4276,6 +4309,12 @@ var databaseAccountOfferType_STATUS_Values = map[string]DatabaseAccountOfferType // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type DatabaseAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` } @@ -4283,6 +4322,42 @@ type DatabaseAccountOperatorSpec struct { // AssignProperties_From_DatabaseAccountOperatorSpec populates our DatabaseAccountOperatorSpec from the provided source DatabaseAccountOperatorSpec func (operator *DatabaseAccountOperatorSpec) AssignProperties_From_DatabaseAccountOperatorSpec(source *storage.DatabaseAccountOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret DatabaseAccountOperatorSecrets @@ -4304,6 +4379,42 @@ func (operator *DatabaseAccountOperatorSpec) AssignProperties_To_DatabaseAccount // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.DatabaseAccountOperatorSecrets diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen.go index 1f1b6ee8fb1..521afe85768 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the MongodbDatabaseCollectionThroughputSetting resource func (setting *MongodbDatabaseCollectionThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollectionThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) ValidateUpdate(old ru // createValidations validates the creation of the resource func (setting *MongodbDatabaseCollectionThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) updateValidations() [ func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *MongodbDatabaseCollectionThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) validateResourceRefer return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *MongodbDatabaseCollectionThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *MongodbDatabaseCollectionThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseCollectionThroughputSetting) @@ -324,6 +369,10 @@ type MongodbDatabaseCollectionThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseCollectionThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -395,6 +444,8 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) PopulateFromARM( setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -483,6 +534,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -518,6 +581,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -778,6 +853,110 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_STATUS) AssignProperti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates our MongodbDatabaseCollectionThroughputSettingOperatorSpec from the provided source MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseCollectionThroughputSettingOperatorSpec from our MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ThroughputSettingsGetProperties_Resource_STATUS struct { // AutoscaleSettings: Cosmos DB resource for autoscale settings. Either throughput is required or autoscaleSettings is // required, but not both. diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen_test.go index 848b6d6f8ab..f6416cbfd7a 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_collection_throughput_setting_types_gen_test.go @@ -607,6 +607,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting(g gens["Status"] = MongodbDatabaseCollectionThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionThroughputSettingOperatorSpec to MongodbDatabaseCollectionThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing - lazily +// instantiated by MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseCollectionThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -847,6 +944,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetti // AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen.go b/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen.go index d2a44f59c77..25ce6d7f387 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (collection *MongodbDatabaseCollection) defaultAzureName() { // defaultImpl applies the code generated defaults to the MongodbDatabaseCollection resource func (collection *MongodbDatabaseCollection) defaultImpl() { collection.defaultAzureName() } +var _ configmaps.Exporter = &MongodbDatabaseCollection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (collection *MongodbDatabaseCollection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (collection *MongodbDatabaseCollection) SecretDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollection{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (collection *MongodbDatabaseCollection) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (collection *MongodbDatabaseCollection) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){collection.validateResourceReferences, collection.validateOwnerReference} + return []func() (admission.Warnings, error){collection.validateResourceReferences, collection.validateOwnerReference, collection.validateSecretDestinations, collection.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (collection *MongodbDatabaseCollection) updateValidations() []func(old runt func(old runtime.Object) (admission.Warnings, error) { return collection.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return collection.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return collection.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (collection *MongodbDatabaseCollection) validateConfigMapDestinations() (admission.Warnings, error) { + if collection.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(collection, nil, collection.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (collection *MongodbDatabaseCollection) validateResourceReferences() (admis return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (collection *MongodbDatabaseCollection) validateSecretDestinations() (admission.Warnings, error) { + if collection.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(collection, nil, collection.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (collection *MongodbDatabaseCollection) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseCollection) @@ -336,6 +381,10 @@ type MongodbDatabaseCollection_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseCollectionOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (collection *MongodbDatabaseCollection_Spec) PopulateFromARM(owner genrunti collection.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_From_MongodbD // Location collection.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + collection.OperatorSpec = &operatorSpec + } else { + collection.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_To_MongodbDat // Location destination.Location = genruntime.ClonePointerToString(collection.Location) + // OperatorSpec + if collection.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionOperatorSpec + err := collection.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if collection.Options != nil { var option storage.CreateUpdateOptions @@ -1268,6 +1343,110 @@ func (resource *MongoDBCollectionResource) AssignProperties_To_MongoDBCollection return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionOperatorSpec populates our MongodbDatabaseCollectionOperatorSpec from the provided source MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source *storage.MongodbDatabaseCollectionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionOperatorSpec populates the provided destination MongodbDatabaseCollectionOperatorSpec from our MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(destination *storage.MongodbDatabaseCollectionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB MongoDB collection index key type MongoIndex struct { // Key: Cosmos DB MongoDB collection index keys diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen_test.go b/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen_test.go index 2be2e69d008..c11271704af 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_collection_types_gen_test.go @@ -1029,6 +1029,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection(gens map[string]go gens["Status"] = MongodbDatabaseCollection_STATUSGenerator() } +func Test_MongodbDatabaseCollectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionOperatorSpec to MongodbDatabaseCollectionOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec tests if a specific instance of MongodbDatabaseCollectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.MongodbDatabaseCollectionOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseCollectionOperatorSpecGenerator() +var mongodbDatabaseCollectionOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionOperatorSpec instances for property testing. +func MongodbDatabaseCollectionOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionOperatorSpec{}), generators) + + return mongodbDatabaseCollectionOperatorSpecGenerator +} + func Test_MongodbDatabaseCollection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1271,6 +1368,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[ // AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBCollectionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen.go index fdd2c07dfc1..e564f1fc36a 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (setting *MongodbDatabaseThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the MongodbDatabaseThroughputSetting resource func (setting *MongodbDatabaseThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &MongodbDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (setting *MongodbDatabaseThroughputSetting) ValidateUpdate(old runtime.Obje // createValidations validates the creation of the resource func (setting *MongodbDatabaseThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (setting *MongodbDatabaseThroughputSetting) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *MongodbDatabaseThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (setting *MongodbDatabaseThroughputSetting) validateResourceReferences() (a return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *MongodbDatabaseThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *MongodbDatabaseThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseThroughputSetting) @@ -324,6 +369,10 @@ type MongodbDatabaseThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -395,6 +444,8 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) PopulateFromARM(owner genr setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -483,6 +534,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_From_Mong // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -518,6 +581,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_To_Mongod // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -778,6 +853,110 @@ func (setting *MongodbDatabaseThroughputSetting_STATUS) AssignProperties_To_Mong return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec populates our MongodbDatabaseThroughputSettingOperatorSpec from the provided source MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseThroughputSettingOperatorSpec from our MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&MongodbDatabaseThroughputSetting{}, &MongodbDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen_test.go index 4e7fc1400fe..1c84c2d6a93 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_throughput_setting_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting(gens map[st gens["Status"] = MongodbDatabaseThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseThroughputSettingOperatorSpec to MongodbDatabaseThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.MongodbDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(ge // AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_types_gen.go b/v2/api/documentdb/v1api20210515/mongodb_database_types_gen.go index c9ba262ffd2..725fc69242b 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_types_gen.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *MongodbDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the MongodbDatabase resource func (database *MongodbDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &MongodbDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *MongodbDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *MongodbDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *MongodbDatabase) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (database *MongodbDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *MongodbDatabase) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *MongodbDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *MongodbDatabase) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *MongodbDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *MongodbDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabase) @@ -336,6 +381,10 @@ type MongodbDatabase_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (database *MongodbDatabase_Spec) PopulateFromARM(owner genruntime.Arbitrary database.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_From_MongodbDatabase_Spec // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_To_MongodbDatabase_Spec(d // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_MongodbDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -1129,6 +1204,110 @@ func (resource *MongoDBDatabaseGetProperties_Resource_STATUS) AssignProperties_T return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseOperatorSpec populates our MongodbDatabaseOperatorSpec from the provided source MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_From_MongodbDatabaseOperatorSpec(source *storage.MongodbDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseOperatorSpec populates the provided destination MongodbDatabaseOperatorSpec from our MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_To_MongodbDatabaseOperatorSpec(destination *storage.MongodbDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB MongoDB database resource object type MongoDBDatabaseResource struct { // +kubebuilder:validation:Required diff --git a/v2/api/documentdb/v1api20210515/mongodb_database_types_gen_test.go b/v2/api/documentdb/v1api20210515/mongodb_database_types_gen_test.go index de3666355a3..fcd593b045b 100644 --- a/v2/api/documentdb/v1api20210515/mongodb_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/mongodb_database_types_gen_test.go @@ -696,6 +696,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabase(gens map[string]gopter.Gen) gens["Status"] = MongodbDatabase_STATUSGenerator() } +func Test_MongodbDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseOperatorSpec to MongodbDatabaseOperatorSpec via AssignProperties_To_MongodbDatabaseOperatorSpec & AssignProperties_From_MongodbDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec tests if a specific instance of MongodbDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.MongodbDatabaseOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseOperatorSpec runs a test to see if a specific instance of MongodbDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseOperatorSpecGenerator() +var mongodbDatabaseOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseOperatorSpecGenerator returns a generator of MongodbDatabaseOperatorSpec instances for property testing. +func MongodbDatabaseOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseOperatorSpecGenerator != nil { + return mongodbDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseOperatorSpec{}), generators) + + return mongodbDatabaseOperatorSpecGenerator +} + func Test_MongodbDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -938,6 +1035,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForMongodbDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen.go index 6ec233af01a..1bd4a5e3007 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (procedure *SqlDatabaseContainerStoredProcedure) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerStoredProcedure resource func (procedure *SqlDatabaseContainerStoredProcedure) defaultImpl() { procedure.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) SecretDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerStoredProcedure{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (procedure *SqlDatabaseContainerStoredProcedure) ValidateUpdate(old runtime // createValidations validates the creation of the resource func (procedure *SqlDatabaseContainerStoredProcedure) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){procedure.validateResourceReferences, procedure.validateOwnerReference} + return []func() (admission.Warnings, error){procedure.validateResourceReferences, procedure.validateOwnerReference, procedure.validateSecretDestinations, procedure.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (procedure *SqlDatabaseContainerStoredProcedure) updateValidations() []func func(old runtime.Object) (admission.Warnings, error) { return procedure.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return procedure.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return procedure.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (procedure *SqlDatabaseContainerStoredProcedure) validateConfigMapDestinations() (admission.Warnings, error) { + if procedure.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(procedure, nil, procedure.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (procedure *SqlDatabaseContainerStoredProcedure) validateResourceReferences return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (procedure *SqlDatabaseContainerStoredProcedure) validateSecretDestinations() (admission.Warnings, error) { + if procedure.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(procedure, nil, procedure.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (procedure *SqlDatabaseContainerStoredProcedure) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerStoredProcedure) @@ -336,6 +381,10 @@ type SqlDatabaseContainerStoredProcedure_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerStoredProcedureOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) PopulateFromARM(owner procedure.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_From // Location procedure.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerStoredProcedureOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + procedure.OperatorSpec = &operatorSpec + } else { + procedure.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(procedure.Location) + // OperatorSpec + if procedure.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerStoredProcedureOperatorSpec + err := procedure.OperatorSpec.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if procedure.Options != nil { var option storage.CreateUpdateOptions @@ -854,6 +929,110 @@ func (procedure *SqlDatabaseContainerStoredProcedure_STATUS) AssignProperties_To return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerStoredProcedureOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec populates our SqlDatabaseContainerStoredProcedureOperatorSpec from the provided source SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec populates the provided destination SqlDatabaseContainerStoredProcedureOperatorSpec from our SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(destination *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlStoredProcedureGetProperties_Resource_STATUS struct { // Body: Body of the Stored Procedure Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen_test.go index 8cde340b3b9..3f151b6dd65 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_stored_procedure_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure(gens map gens["Status"] = SqlDatabaseContainerStoredProcedure_STATUSGenerator() } +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerStoredProcedureOperatorSpec to SqlDatabaseContainerStoredProcedureOperatorSpec via AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec & AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec tests if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseContainerStoredProcedureOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerStoredProcedureOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() +var sqlDatabaseContainerStoredProcedureOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator returns a generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing. +func SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerStoredProcedureOperatorSpecGenerator != nil { + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerStoredProcedureOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerStoredProcedureOperatorSpec{}), generators) + + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator +} + func Test_SqlDatabaseContainerStoredProcedure_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec // AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerStoredProcedureOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlStoredProcedureResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen.go index 95bc63678d7..c394664db1f 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (setting *SqlDatabaseContainerThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerThroughputSetting resource func (setting *SqlDatabaseContainerThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (setting *SqlDatabaseContainerThroughputSetting) ValidateUpdate(old runtime // createValidations validates the creation of the resource func (setting *SqlDatabaseContainerThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (setting *SqlDatabaseContainerThroughputSetting) updateValidations() []func func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *SqlDatabaseContainerThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (setting *SqlDatabaseContainerThroughputSetting) validateResourceReferences return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *SqlDatabaseContainerThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *SqlDatabaseContainerThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerThroughputSetting) @@ -324,6 +369,10 @@ type SqlDatabaseContainerThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -395,6 +444,8 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) PopulateFromARM(owner setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -483,6 +534,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_From // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -518,6 +581,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -778,6 +853,110 @@ func (setting *SqlDatabaseContainerThroughputSetting_STATUS) AssignProperties_To return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec populates our SqlDatabaseContainerThroughputSettingOperatorSpec from the provided source SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec populates the provided destination SqlDatabaseContainerThroughputSettingOperatorSpec from our SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(destination *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlDatabaseContainerThroughputSetting{}, &SqlDatabaseContainerThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen_test.go index ce8c53bc9e5..e86a5d3d43f 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_throughput_setting_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting(gens m gens["Status"] = SqlDatabaseContainerThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerThroughputSettingOperatorSpec to SqlDatabaseContainerThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseContainerThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() +var sqlDatabaseContainerThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseContainerThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Sp // AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen.go index fce74898b54..56eeb4057c9 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (trigger *SqlDatabaseContainerTrigger) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerTrigger resource func (trigger *SqlDatabaseContainerTrigger) defaultImpl() { trigger.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerTrigger{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (trigger *SqlDatabaseContainerTrigger) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerTrigger{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (trigger *SqlDatabaseContainerTrigger) SecretDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerTrigger{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (trigger *SqlDatabaseContainerTrigger) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (trigger *SqlDatabaseContainerTrigger) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){trigger.validateResourceReferences, trigger.validateOwnerReference} + return []func() (admission.Warnings, error){trigger.validateResourceReferences, trigger.validateOwnerReference, trigger.validateSecretDestinations, trigger.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (trigger *SqlDatabaseContainerTrigger) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return trigger.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return trigger.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return trigger.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (trigger *SqlDatabaseContainerTrigger) validateConfigMapDestinations() (admission.Warnings, error) { + if trigger.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(trigger, nil, trigger.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (trigger *SqlDatabaseContainerTrigger) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (trigger *SqlDatabaseContainerTrigger) validateSecretDestinations() (admission.Warnings, error) { + if trigger.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(trigger, nil, trigger.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (trigger *SqlDatabaseContainerTrigger) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerTrigger) @@ -336,6 +381,10 @@ type SqlDatabaseContainerTrigger_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerTriggerOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) PopulateFromARM(owner genruntim trigger.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_From_SqlDataba // Location trigger.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerTriggerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + trigger.OperatorSpec = &operatorSpec + } else { + trigger.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_To_SqlDatabase // Location destination.Location = genruntime.ClonePointerToString(trigger.Location) + // OperatorSpec + if trigger.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerTriggerOperatorSpec + err := trigger.OperatorSpec.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if trigger.Options != nil { var option storage.CreateUpdateOptions @@ -854,6 +929,110 @@ func (trigger *SqlDatabaseContainerTrigger_STATUS) AssignProperties_To_SqlDataba return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerTriggerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec populates our SqlDatabaseContainerTriggerOperatorSpec from the provided source SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec populates the provided destination SqlDatabaseContainerTriggerOperatorSpec from our SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(destination *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlTriggerGetProperties_Resource_STATUS struct { // Body: Body of the Trigger Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen_test.go index a9ebc92efcc..eed10aea890 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_trigger_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger(gens map[string] gens["Status"] = SqlDatabaseContainerTrigger_STATUSGenerator() } +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerTriggerOperatorSpec to SqlDatabaseContainerTriggerOperatorSpec via AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec & AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec tests if a specific instance of SqlDatabaseContainerTriggerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseContainerTriggerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerTriggerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerTriggerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerTriggerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerTriggerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerTriggerOperatorSpecGenerator() +var sqlDatabaseContainerTriggerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerTriggerOperatorSpecGenerator returns a generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing. +func SqlDatabaseContainerTriggerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerTriggerOperatorSpecGenerator != nil { + return sqlDatabaseContainerTriggerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerTriggerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerTriggerOperatorSpec{}), generators) + + return sqlDatabaseContainerTriggerOperatorSpecGenerator +} + func Test_SqlDatabaseContainerTrigger_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens ma // AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerTriggerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlTriggerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_container_types_gen.go index 074876e864b..553b1c0a628 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (container *SqlDatabaseContainer) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainer resource func (container *SqlDatabaseContainer) defaultImpl() { container.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *SqlDatabaseContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *SqlDatabaseContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainer{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (container *SqlDatabaseContainer) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (container *SqlDatabaseContainer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference} + return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference, container.validateSecretDestinations, container.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (container *SqlDatabaseContainer) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return container.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (container *SqlDatabaseContainer) validateConfigMapDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(container, nil, container.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (container *SqlDatabaseContainer) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (container *SqlDatabaseContainer) validateSecretDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(container, nil, container.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (container *SqlDatabaseContainer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainer) @@ -336,6 +381,10 @@ type SqlDatabaseContainer_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (container *SqlDatabaseContainer_Spec) PopulateFromARM(owner genruntime.Arb container.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_From_SqlDatabaseCon // Location container.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_To_SqlDatabaseConta // Location destination.Location = genruntime.ClonePointerToString(container.Location) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if container.Options != nil { var option storage.CreateUpdateOptions @@ -1503,6 +1578,110 @@ func (resource *SqlContainerResource) AssignProperties_To_SqlContainerResource(d return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerOperatorSpec populates our SqlDatabaseContainerOperatorSpec from the provided source SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_From_SqlDatabaseContainerOperatorSpec(source *storage.SqlDatabaseContainerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerOperatorSpec populates the provided destination SqlDatabaseContainerOperatorSpec from our SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_To_SqlDatabaseContainerOperatorSpec(destination *storage.SqlDatabaseContainerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The conflict resolution policy for the container. type ConflictResolutionPolicy struct { // ConflictResolutionPath: The conflict resolution path in the case of LastWriterWins mode. diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_container_types_gen_test.go index 0035e9caaf5..e219a2ffcf7 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_types_gen_test.go @@ -2154,6 +2154,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainer(gens map[string]gopter. gens["Status"] = SqlDatabaseContainer_STATUSGenerator() } +func Test_SqlDatabaseContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerOperatorSpec to SqlDatabaseContainerOperatorSpec via AssignProperties_To_SqlDatabaseContainerOperatorSpec & AssignProperties_From_SqlDatabaseContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec tests if a specific instance of SqlDatabaseContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseContainerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerOperatorSpecGenerator() +var sqlDatabaseContainerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerOperatorSpecGenerator returns a generator of SqlDatabaseContainerOperatorSpec instances for property testing. +func SqlDatabaseContainerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerOperatorSpecGenerator != nil { + return sqlDatabaseContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerOperatorSpec{}), generators) + + return sqlDatabaseContainerOperatorSpecGenerator +} + func Test_SqlDatabaseContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2396,6 +2493,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[strin // AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlContainerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen.go index 07130a622e3..8a8ec449591 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (function *SqlDatabaseContainerUserDefinedFunction) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerUserDefinedFunction resource func (function *SqlDatabaseContainerUserDefinedFunction) defaultImpl() { function.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) SecretDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerUserDefinedFunction{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (function *SqlDatabaseContainerUserDefinedFunction) ValidateUpdate(old runt // createValidations validates the creation of the resource func (function *SqlDatabaseContainerUserDefinedFunction) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){function.validateResourceReferences, function.validateOwnerReference} + return []func() (admission.Warnings, error){function.validateResourceReferences, function.validateOwnerReference, function.validateSecretDestinations, function.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (function *SqlDatabaseContainerUserDefinedFunction) updateValidations() []f func(old runtime.Object) (admission.Warnings, error) { return function.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return function.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return function.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (function *SqlDatabaseContainerUserDefinedFunction) validateConfigMapDestinations() (admission.Warnings, error) { + if function.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(function, nil, function.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (function *SqlDatabaseContainerUserDefinedFunction) validateResourceReferen return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (function *SqlDatabaseContainerUserDefinedFunction) validateSecretDestinations() (admission.Warnings, error) { + if function.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(function, nil, function.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (function *SqlDatabaseContainerUserDefinedFunction) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerUserDefinedFunction) @@ -336,6 +381,10 @@ type SqlDatabaseContainerUserDefinedFunction_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerUserDefinedFunctionOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) PopulateFromARM(ow function.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_F // Location function.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + function.OperatorSpec = &operatorSpec + } else { + function.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_T // Location destination.Location = genruntime.ClonePointerToString(function.Location) + // OperatorSpec + if function.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := function.OperatorSpec.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if function.Options != nil { var option storage.CreateUpdateOptions @@ -854,6 +929,110 @@ func (function *SqlDatabaseContainerUserDefinedFunction_STATUS) AssignProperties return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerUserDefinedFunctionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates our SqlDatabaseContainerUserDefinedFunctionOperatorSpec from the provided source SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates the provided destination SqlDatabaseContainerUserDefinedFunctionOperatorSpec from our SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(destination *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlUserDefinedFunctionGetProperties_Resource_STATUS struct { // Body: Body of the User Defined Function Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen_test.go index 063c77c0efa..4acf1691808 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_container_user_defined_function_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction(gens gens["Status"] = SqlDatabaseContainerUserDefinedFunction_STATUSGenerator() } +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerUserDefinedFunctionOperatorSpec to SqlDatabaseContainerUserDefinedFunctionOperatorSpec via AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec & AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec tests if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerUserDefinedFunctionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() +var sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator returns a generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing. +func SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator != nil { + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpec{}), generators) + + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator +} + func Test_SqlDatabaseContainerUserDefinedFunction_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_ // AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlUserDefinedFunctionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen.go index 9afcd1da62f..2ef88889b43 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (setting *SqlDatabaseThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the SqlDatabaseThroughputSetting resource func (setting *SqlDatabaseThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &SqlDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (setting *SqlDatabaseThroughputSetting) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (setting *SqlDatabaseThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (setting *SqlDatabaseThroughputSetting) updateValidations() []func(old runt func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *SqlDatabaseThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (setting *SqlDatabaseThroughputSetting) validateResourceReferences() (admis return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *SqlDatabaseThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *SqlDatabaseThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseThroughputSetting) @@ -324,6 +369,10 @@ type SqlDatabaseThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -395,6 +444,8 @@ func (setting *SqlDatabaseThroughputSetting_Spec) PopulateFromARM(owner genrunti setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -483,6 +534,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_From_SqlDatab // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -518,6 +581,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_To_SqlDatabas // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -778,6 +853,110 @@ func (setting *SqlDatabaseThroughputSetting_STATUS) AssignProperties_To_SqlDatab return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec populates our SqlDatabaseThroughputSettingOperatorSpec from the provided source SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec populates the provided destination SqlDatabaseThroughputSettingOperatorSpec from our SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(destination *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlDatabaseThroughputSetting{}, &SqlDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen_test.go index d2f710e11a1..97bb767cd61 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_throughput_setting_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting(gens map[string gens["Status"] = SqlDatabaseThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseThroughputSettingOperatorSpec to SqlDatabaseThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseThroughputSettingOperatorSpecGenerator() +var sqlDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens m // AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_database_types_gen.go b/v2/api/documentdb/v1api20210515/sql_database_types_gen.go index a706b1232c2..f55a7e1f43b 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (database *SqlDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabase resource func (database *SqlDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *SqlDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *SqlDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabase{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (database *SqlDatabase) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (database *SqlDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (database *SqlDatabase) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *SqlDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (database *SqlDatabase) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *SqlDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *SqlDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabase) @@ -336,6 +381,10 @@ type SqlDatabase_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -422,6 +471,8 @@ func (database *SqlDatabase_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne database.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -527,6 +578,18 @@ func (database *SqlDatabase_Spec) AssignProperties_From_SqlDatabase_Spec(source // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -577,6 +640,18 @@ func (database *SqlDatabase_Spec) AssignProperties_To_SqlDatabase_Spec(destinati // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_SqlDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -1036,6 +1111,110 @@ func (resource *SqlDatabaseGetProperties_Resource_STATUS) AssignProperties_To_Sq return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseOperatorSpec populates our SqlDatabaseOperatorSpec from the provided source SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_From_SqlDatabaseOperatorSpec(source *storage.SqlDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseOperatorSpec populates the provided destination SqlDatabaseOperatorSpec from our SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_To_SqlDatabaseOperatorSpec(destination *storage.SqlDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB SQL database resource object type SqlDatabaseResource struct { // +kubebuilder:validation:Required diff --git a/v2/api/documentdb/v1api20210515/sql_database_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_database_types_gen_test.go index d3fe8af258b..a59c284648b 100644 --- a/v2/api/documentdb/v1api20210515/sql_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_database_types_gen_test.go @@ -273,6 +273,103 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseGetProperties_Resource_STATUS gens["Users"] = gen.PtrOf(gen.AlphaString()) } +func Test_SqlDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseOperatorSpec to SqlDatabaseOperatorSpec via AssignProperties_To_SqlDatabaseOperatorSpec & AssignProperties_From_SqlDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseOperatorSpec tests if a specific instance of SqlDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlDatabaseOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseOperatorSpec runs a test to see if a specific instance of SqlDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseOperatorSpecGenerator() +var sqlDatabaseOperatorSpecGenerator gopter.Gen + +// SqlDatabaseOperatorSpecGenerator returns a generator of SqlDatabaseOperatorSpec instances for property testing. +func SqlDatabaseOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseOperatorSpecGenerator != nil { + return sqlDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseOperatorSpec{}), generators) + + return sqlDatabaseOperatorSpecGenerator +} + func Test_SqlDatabaseResource_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -616,6 +713,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForSqlDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen.go b/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen.go index 392ff89d480..92f0355f8e1 100644 --- a/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen.go +++ b/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -99,6 +101,26 @@ func (assignment *SqlRoleAssignment) Default() { // defaultImpl applies the code generated defaults to the SqlRoleAssignment resource func (assignment *SqlRoleAssignment) defaultImpl() {} +var _ configmaps.Exporter = &SqlRoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *SqlRoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlRoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *SqlRoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlRoleAssignment{} // AzureName returns the Azure name of the resource @@ -206,7 +228,7 @@ func (assignment *SqlRoleAssignment) ValidateUpdate(old runtime.Object) (admissi // createValidations validates the creation of the resource func (assignment *SqlRoleAssignment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOwnerReference, assignment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOwnerReference, assignment.validateSecretDestinations, assignment.validateConfigMapDestinations, assignment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -224,12 +246,26 @@ func (assignment *SqlRoleAssignment) updateValidations() []func(old runtime.Obje func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assignment *SqlRoleAssignment) validateConfigMapDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assignment *SqlRoleAssignment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assignment.Spec) @@ -253,6 +289,14 @@ func (assignment *SqlRoleAssignment) validateResourceReferences() (admission.War return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assignment *SqlRoleAssignment) validateSecretDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assignment *SqlRoleAssignment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlRoleAssignment) @@ -339,6 +383,10 @@ type SqlRoleAssignment_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlRoleAssignmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -418,6 +466,8 @@ func (assignment *SqlRoleAssignment_Spec) PopulateFromARM(owner genruntime.Arbit // Set property "AzureName": assignment.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": assignment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -513,6 +563,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_From_SqlRoleAssignmen // AzureName assignment.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlRoleAssignmentOperatorSpec + err := operatorSpec.AssignProperties_From_SqlRoleAssignmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + assignment.OperatorSpec = &operatorSpec + } else { + assignment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -550,6 +612,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_To_SqlRoleAssignment_ // AzureName destination.AzureName = assignment.AzureName + // OperatorSpec + if assignment.OperatorSpec != nil { + var operatorSpec storage.SqlRoleAssignmentOperatorSpec + err := assignment.OperatorSpec.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = assignment.OriginalVersion() @@ -803,6 +877,110 @@ func (assignment *SqlRoleAssignment_STATUS) AssignProperties_To_SqlRoleAssignmen return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlRoleAssignmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlRoleAssignmentOperatorSpec populates our SqlRoleAssignmentOperatorSpec from the provided source SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_From_SqlRoleAssignmentOperatorSpec(source *storage.SqlRoleAssignmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlRoleAssignmentOperatorSpec populates the provided destination SqlRoleAssignmentOperatorSpec from our SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_To_SqlRoleAssignmentOperatorSpec(destination *storage.SqlRoleAssignmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlRoleAssignment{}, &SqlRoleAssignmentList{}) } diff --git a/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen_test.go b/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen_test.go index 772eda48e9a..ad70e652fd8 100644 --- a/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/sql_role_assignment_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlRoleAssignment(gens map[string]gopter.Gen gens["Status"] = SqlRoleAssignment_STATUSGenerator() } +func Test_SqlRoleAssignmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlRoleAssignmentOperatorSpec to SqlRoleAssignmentOperatorSpec via AssignProperties_To_SqlRoleAssignmentOperatorSpec & AssignProperties_From_SqlRoleAssignmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec tests if a specific instance of SqlRoleAssignmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210515s.SqlRoleAssignmentOperatorSpec + err := copied.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlRoleAssignmentOperatorSpec + err = actual.AssignProperties_From_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlRoleAssignmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlRoleAssignmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec runs a test to see if a specific instance of SqlRoleAssignmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlRoleAssignmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlRoleAssignmentOperatorSpec instances for property testing - lazily instantiated by +// SqlRoleAssignmentOperatorSpecGenerator() +var sqlRoleAssignmentOperatorSpecGenerator gopter.Gen + +// SqlRoleAssignmentOperatorSpecGenerator returns a generator of SqlRoleAssignmentOperatorSpec instances for property testing. +func SqlRoleAssignmentOperatorSpecGenerator() gopter.Gen { + if sqlRoleAssignmentOperatorSpecGenerator != nil { + return sqlRoleAssignmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlRoleAssignmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignmentOperatorSpec{}), generators) + + return sqlRoleAssignmentOperatorSpecGenerator +} + func Test_SqlRoleAssignment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForSqlRoleAssignment_Spec(subject SqlRoleAssignment var sqlRoleAssignment_SpecGenerator gopter.Gen // SqlRoleAssignment_SpecGenerator returns a generator of SqlRoleAssignment_Spec instances for property testing. +// We first initialize sqlRoleAssignment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func SqlRoleAssignment_SpecGenerator() gopter.Gen { if sqlRoleAssignment_SpecGenerator != nil { return sqlRoleAssignment_SpecGenerator @@ -368,6 +468,12 @@ func SqlRoleAssignment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + return sqlRoleAssignment_SpecGenerator } @@ -378,3 +484,8 @@ func AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]g gens["RoleDefinitionId"] = gen.PtrOf(gen.AlphaString()) gens["Scope"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlRoleAssignmentOperatorSpecGenerator()) +} diff --git a/v2/api/documentdb/v1api20210515/storage/database_account_types_gen.go b/v2/api/documentdb/v1api20210515/storage/database_account_types_gen.go index 6de6cf03980..b6d0a36f989 100644 --- a/v2/api/documentdb/v1api20210515/storage/database_account_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/database_account_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (account *DatabaseAccount) ConvertTo(hub conversion.Hub) error { return account.AssignProperties_To_DatabaseAccount(destination) } +var _ configmaps.Exporter = &DatabaseAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *DatabaseAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DatabaseAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *DatabaseAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DatabaseAccount{} // AzureName returns the Azure name of the resource @@ -3048,8 +3071,10 @@ func (policy *CorsPolicy_STATUS) AssignProperties_To_CorsPolicy_STATUS(destinati // Storage version of v1api20210515.DatabaseAccountOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type DatabaseAccountOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_DatabaseAccountOperatorSpec populates our DatabaseAccountOperatorSpec from the provided source DatabaseAccountOperatorSpec @@ -3057,6 +3082,42 @@ func (operator *DatabaseAccountOperatorSpec) AssignProperties_From_DatabaseAccou // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret DatabaseAccountOperatorSecrets @@ -3094,6 +3155,42 @@ func (operator *DatabaseAccountOperatorSpec) AssignProperties_To_DatabaseAccount // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.DatabaseAccountOperatorSecrets diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen.go index 175358b98f3..923d2667c28 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) ConvertTo(hub convers return setting.AssignProperties_To_MongodbDatabaseCollectionThroughputSetting(destination) } +var _ configmaps.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollectionThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForMongodbDatabaseCollectionThroughputSetting interface { // Storage version of v1api20210515.MongodbDatabaseCollectionThroughputSetting_Spec type MongodbDatabaseCollectionThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseCollectionThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -303,6 +327,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // OriginalVersion setting.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion @@ -585,6 +633,136 @@ type augmentConversionForMongodbDatabaseCollectionThroughputSetting_STATUS inter AssignPropertiesTo(dst *storage.MongodbDatabaseCollectionThroughputSetting_STATUS) error } +// Storage version of v1api20210515.MongodbDatabaseCollectionThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates our MongodbDatabaseCollectionThroughputSettingOperatorSpec from the provided source MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseCollectionThroughputSettingOperatorSpec from our MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.ThroughputSettingsGetProperties_Resource_STATUS type ThroughputSettingsGetProperties_Resource_STATUS struct { AutoscaleSettings *AutoscaleSettingsResource_STATUS `json:"autoscaleSettings,omitempty"` @@ -845,6 +1023,11 @@ func (resource *ThroughputSettingsResource) AssignProperties_To_ThroughputSettin return nil } +type augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec interface { + AssignPropertiesFrom(src *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error + AssignPropertiesTo(dst *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error +} + type augmentConversionForThroughputSettingsGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.ThroughputSettingsGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.ThroughputSettingsGetProperties_Resource_STATUS) error diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen_test.go index 27b46852877..3742f7bc1da 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_throughput_setting_types_gen_test.go @@ -606,6 +606,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting(g gens["Status"] = MongodbDatabaseCollectionThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionThroughputSettingOperatorSpec to MongodbDatabaseCollectionThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing - lazily +// instantiated by MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseCollectionThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -847,6 +944,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetti // AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen.go index 626339602a3..e3a47f14e63 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (collection *MongodbDatabaseCollection) ConvertTo(hub conversion.Hub) error return collection.AssignProperties_To_MongodbDatabaseCollection(destination) } +var _ configmaps.Exporter = &MongodbDatabaseCollection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (collection *MongodbDatabaseCollection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (collection *MongodbDatabaseCollection) SecretDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollection{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForMongodbDatabaseCollection interface { type MongodbDatabaseCollection_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseCollectionOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_From_MongodbD // Location collection.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + collection.OperatorSpec = &operatorSpec + } else { + collection.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_To_MongodbDat // Location destination.Location = genruntime.ClonePointerToString(collection.Location) + // OperatorSpec + if collection.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionOperatorSpec + err := collection.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if collection.Options != nil { var option storage.CreateUpdateOptions @@ -983,6 +1031,136 @@ func (resource *MongoDBCollectionResource) AssignProperties_To_MongoDBCollection return nil } +// Storage version of v1api20210515.MongodbDatabaseCollectionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionOperatorSpec populates our MongodbDatabaseCollectionOperatorSpec from the provided source MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source *storage.MongodbDatabaseCollectionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseCollectionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseCollectionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionOperatorSpec populates the provided destination MongodbDatabaseCollectionOperatorSpec from our MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(destination *storage.MongodbDatabaseCollectionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseCollectionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseCollectionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForMongoDBCollectionGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.MongoDBCollectionGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.MongoDBCollectionGetProperties_Resource_STATUS) error @@ -993,6 +1171,11 @@ type augmentConversionForMongoDBCollectionResource interface { AssignPropertiesTo(dst *storage.MongoDBCollectionResource) error } +type augmentConversionForMongodbDatabaseCollectionOperatorSpec interface { + AssignPropertiesFrom(src *storage.MongodbDatabaseCollectionOperatorSpec) error + AssignPropertiesTo(dst *storage.MongodbDatabaseCollectionOperatorSpec) error +} + // Storage version of v1api20210515.MongoIndex // Cosmos DB MongoDB collection index key type MongoIndex struct { diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen_test.go index b64136fbedc..b2748dcbc7e 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_collection_types_gen_test.go @@ -1028,6 +1028,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection(gens map[string]go gens["Status"] = MongodbDatabaseCollection_STATUSGenerator() } +func Test_MongodbDatabaseCollectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionOperatorSpec to MongodbDatabaseCollectionOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec tests if a specific instance of MongodbDatabaseCollectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseCollectionOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseCollectionOperatorSpecGenerator() +var mongodbDatabaseCollectionOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionOperatorSpec instances for property testing. +func MongodbDatabaseCollectionOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionOperatorSpec{}), generators) + + return mongodbDatabaseCollectionOperatorSpecGenerator +} + func Test_MongodbDatabaseCollection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1271,6 +1368,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[ // AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBCollectionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen.go index ee5b3ba1862..9218af0e415 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (setting *MongodbDatabaseThroughputSetting) ConvertTo(hub conversion.Hub) e return setting.AssignProperties_To_MongodbDatabaseThroughputSetting(destination) } +var _ configmaps.Exporter = &MongodbDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForMongodbDatabaseThroughputSetting interface { // Storage version of v1api20210515.MongodbDatabaseThroughputSetting_Spec type MongodbDatabaseThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -303,6 +327,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_From_Mong // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // OriginalVersion setting.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_To_Mongod // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion @@ -585,6 +633,141 @@ type augmentConversionForMongodbDatabaseThroughputSetting_STATUS interface { AssignPropertiesTo(dst *storage.MongodbDatabaseThroughputSetting_STATUS) error } +// Storage version of v1api20210515.MongodbDatabaseThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec populates our MongodbDatabaseThroughputSettingOperatorSpec from the provided source MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseThroughputSettingOperatorSpec from our MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec interface { + AssignPropertiesFrom(src *storage.MongodbDatabaseThroughputSettingOperatorSpec) error + AssignPropertiesTo(dst *storage.MongodbDatabaseThroughputSettingOperatorSpec) error +} + func init() { SchemeBuilder.Register(&MongodbDatabaseThroughputSetting{}, &MongodbDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen_test.go index ad2e37f12e3..d6da6085f3f 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting(gens map[st gens["Status"] = MongodbDatabaseThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseThroughputSettingOperatorSpec to MongodbDatabaseThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(ge // AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen.go index 5956c7cc1ce..5450e90d38c 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (database *MongodbDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_MongodbDatabase(destination) } +var _ configmaps.Exporter = &MongodbDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *MongodbDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *MongodbDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabase{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForMongodbDatabase interface { type MongodbDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_From_MongodbDatabase_Spec // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_To_MongodbDatabase_Spec(d // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_MongodbDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -867,6 +915,136 @@ func (resource *MongoDBDatabaseGetProperties_Resource_STATUS) AssignProperties_T return nil } +// Storage version of v1api20210515.MongodbDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseOperatorSpec populates our MongodbDatabaseOperatorSpec from the provided source MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_From_MongodbDatabaseOperatorSpec(source *storage.MongodbDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseOperatorSpec populates the provided destination MongodbDatabaseOperatorSpec from our MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_To_MongodbDatabaseOperatorSpec(destination *storage.MongodbDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForMongodbDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForMongodbDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.MongoDBDatabaseResource // Cosmos DB MongoDB database resource object type MongoDBDatabaseResource struct { @@ -1068,6 +1246,11 @@ type augmentConversionForMongoDBDatabaseGetProperties_Resource_STATUS interface AssignPropertiesTo(dst *storage.MongoDBDatabaseGetProperties_Resource_STATUS) error } +type augmentConversionForMongodbDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.MongodbDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.MongodbDatabaseOperatorSpec) error +} + type augmentConversionForMongoDBDatabaseResource interface { AssignPropertiesFrom(src *storage.MongoDBDatabaseResource) error AssignPropertiesTo(dst *storage.MongoDBDatabaseResource) error diff --git a/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen_test.go index 3e78e8a33f6..1a03a469e86 100644 --- a/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/mongodb_database_types_gen_test.go @@ -695,6 +695,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabase(gens map[string]gopter.Gen) gens["Status"] = MongodbDatabase_STATUSGenerator() } +func Test_MongodbDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseOperatorSpec to MongodbDatabaseOperatorSpec via AssignProperties_To_MongodbDatabaseOperatorSpec & AssignProperties_From_MongodbDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec tests if a specific instance of MongodbDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseOperatorSpec runs a test to see if a specific instance of MongodbDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseOperatorSpecGenerator() +var mongodbDatabaseOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseOperatorSpecGenerator returns a generator of MongodbDatabaseOperatorSpec instances for property testing. +func MongodbDatabaseOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseOperatorSpecGenerator != nil { + return mongodbDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseOperatorSpec{}), generators) + + return mongodbDatabaseOperatorSpecGenerator +} + func Test_MongodbDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -938,6 +1035,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForMongodbDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen.go index 92d3af036ee..8bb5e7d6697 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (procedure *SqlDatabaseContainerStoredProcedure) ConvertTo(hub conversion.H return procedure.AssignProperties_To_SqlDatabaseContainerStoredProcedure(destination) } +var _ configmaps.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) SecretDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerStoredProcedure{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForSqlDatabaseContainerStoredProcedure interface { type SqlDatabaseContainerStoredProcedure_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerStoredProcedureOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_From // Location procedure.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerStoredProcedureOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + procedure.OperatorSpec = &operatorSpec + } else { + procedure.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(procedure.Location) + // OperatorSpec + if procedure.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerStoredProcedureOperatorSpec + err := procedure.OperatorSpec.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if procedure.Options != nil { var option storage.CreateUpdateOptions @@ -620,6 +668,136 @@ type augmentConversionForSqlDatabaseContainerStoredProcedure_STATUS interface { AssignPropertiesTo(dst *storage.SqlDatabaseContainerStoredProcedure_STATUS) error } +// Storage version of v1api20210515.SqlDatabaseContainerStoredProcedureOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerStoredProcedureOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec populates our SqlDatabaseContainerStoredProcedureOperatorSpec from the provided source SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec populates the provided destination SqlDatabaseContainerStoredProcedureOperatorSpec from our SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(destination *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.SqlStoredProcedureGetProperties_Resource_STATUS type SqlStoredProcedureGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` @@ -790,6 +968,11 @@ func (resource *SqlStoredProcedureResource) AssignProperties_To_SqlStoredProcedu return nil } +type augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error +} + type augmentConversionForSqlStoredProcedureGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.SqlStoredProcedureGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.SqlStoredProcedureGetProperties_Resource_STATUS) error diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen_test.go index 23121290b10..ecb4e6834ed 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_stored_procedure_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure(gens map gens["Status"] = SqlDatabaseContainerStoredProcedure_STATUSGenerator() } +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerStoredProcedureOperatorSpec to SqlDatabaseContainerStoredProcedureOperatorSpec via AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec & AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec tests if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerStoredProcedureOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerStoredProcedureOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() +var sqlDatabaseContainerStoredProcedureOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator returns a generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing. +func SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerStoredProcedureOperatorSpecGenerator != nil { + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerStoredProcedureOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerStoredProcedureOperatorSpec{}), generators) + + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator +} + func Test_SqlDatabaseContainerStoredProcedure_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec // AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerStoredProcedureOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlStoredProcedureResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen.go index 39e5d9b8000..17a3e2c8568 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (setting *SqlDatabaseContainerThroughputSetting) ConvertTo(hub conversion.H return setting.AssignProperties_To_SqlDatabaseContainerThroughputSetting(destination) } +var _ configmaps.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForSqlDatabaseContainerThroughputSetting interface { // Storage version of v1api20210515.SqlDatabaseContainerThroughputSetting_Spec type SqlDatabaseContainerThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -303,6 +327,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_From // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // OriginalVersion setting.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion @@ -585,6 +633,141 @@ type augmentConversionForSqlDatabaseContainerThroughputSetting_STATUS interface AssignPropertiesTo(dst *storage.SqlDatabaseContainerThroughputSetting_STATUS) error } +// Storage version of v1api20210515.SqlDatabaseContainerThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec populates our SqlDatabaseContainerThroughputSettingOperatorSpec from the provided source SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec populates the provided destination SqlDatabaseContainerThroughputSettingOperatorSpec from our SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(destination *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error +} + func init() { SchemeBuilder.Register(&SqlDatabaseContainerThroughputSetting{}, &SqlDatabaseContainerThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen_test.go index 13cc3aa68b3..0511cf232e2 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting(gens m gens["Status"] = SqlDatabaseContainerThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerThroughputSettingOperatorSpec to SqlDatabaseContainerThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() +var sqlDatabaseContainerThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseContainerThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Sp // AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen.go index 720210bb26a..0b3bb5ac593 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (trigger *SqlDatabaseContainerTrigger) ConvertTo(hub conversion.Hub) error return trigger.AssignProperties_To_SqlDatabaseContainerTrigger(destination) } +var _ configmaps.Exporter = &SqlDatabaseContainerTrigger{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (trigger *SqlDatabaseContainerTrigger) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerTrigger{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (trigger *SqlDatabaseContainerTrigger) SecretDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerTrigger{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForSqlDatabaseContainerTrigger interface { type SqlDatabaseContainerTrigger_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerTriggerOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_From_SqlDataba // Location trigger.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerTriggerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + trigger.OperatorSpec = &operatorSpec + } else { + trigger.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_To_SqlDatabase // Location destination.Location = genruntime.ClonePointerToString(trigger.Location) + // OperatorSpec + if trigger.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerTriggerOperatorSpec + err := trigger.OperatorSpec.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if trigger.Options != nil { var option storage.CreateUpdateOptions @@ -620,6 +668,136 @@ type augmentConversionForSqlDatabaseContainerTrigger_STATUS interface { AssignPropertiesTo(dst *storage.SqlDatabaseContainerTrigger_STATUS) error } +// Storage version of v1api20210515.SqlDatabaseContainerTriggerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerTriggerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec populates our SqlDatabaseContainerTriggerOperatorSpec from the provided source SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerTriggerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerTriggerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec populates the provided destination SqlDatabaseContainerTriggerOperatorSpec from our SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(destination *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerTriggerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerTriggerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.SqlTriggerGetProperties_Resource_STATUS type SqlTriggerGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` @@ -818,6 +996,11 @@ func (resource *SqlTriggerResource) AssignProperties_To_SqlTriggerResource(desti return nil } +type augmentConversionForSqlDatabaseContainerTriggerOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseContainerTriggerOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseContainerTriggerOperatorSpec) error +} + type augmentConversionForSqlTriggerGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.SqlTriggerGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.SqlTriggerGetProperties_Resource_STATUS) error diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen_test.go index b8b4a57465f..cff827e6ab7 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_trigger_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger(gens map[string] gens["Status"] = SqlDatabaseContainerTrigger_STATUSGenerator() } +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerTriggerOperatorSpec to SqlDatabaseContainerTriggerOperatorSpec via AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec & AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec tests if a specific instance of SqlDatabaseContainerTriggerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerTriggerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerTriggerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerTriggerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerTriggerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerTriggerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerTriggerOperatorSpecGenerator() +var sqlDatabaseContainerTriggerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerTriggerOperatorSpecGenerator returns a generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing. +func SqlDatabaseContainerTriggerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerTriggerOperatorSpecGenerator != nil { + return sqlDatabaseContainerTriggerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerTriggerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerTriggerOperatorSpec{}), generators) + + return sqlDatabaseContainerTriggerOperatorSpecGenerator +} + func Test_SqlDatabaseContainerTrigger_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens ma // AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerTriggerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlTriggerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen.go index 24ecc1dab89..38e6d36cff2 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (container *SqlDatabaseContainer) ConvertTo(hub conversion.Hub) error { return container.AssignProperties_To_SqlDatabaseContainer(destination) } +var _ configmaps.Exporter = &SqlDatabaseContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *SqlDatabaseContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *SqlDatabaseContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainer{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForSqlDatabaseContainer interface { type SqlDatabaseContainer_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_From_SqlDatabaseCon // Location container.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_To_SqlDatabaseConta // Location destination.Location = genruntime.ClonePointerToString(container.Location) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if container.Options != nil { var option storage.CreateUpdateOptions @@ -1189,6 +1237,136 @@ func (resource *SqlContainerResource) AssignProperties_To_SqlContainerResource(d return nil } +// Storage version of v1api20210515.SqlDatabaseContainerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerOperatorSpec populates our SqlDatabaseContainerOperatorSpec from the provided source SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_From_SqlDatabaseContainerOperatorSpec(source *storage.SqlDatabaseContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerOperatorSpec populates the provided destination SqlDatabaseContainerOperatorSpec from our SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_To_SqlDatabaseContainerOperatorSpec(destination *storage.SqlDatabaseContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForSqlContainerGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.SqlContainerGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.SqlContainerGetProperties_Resource_STATUS) error @@ -1199,6 +1377,11 @@ type augmentConversionForSqlContainerResource interface { AssignPropertiesTo(dst *storage.SqlContainerResource) error } +type augmentConversionForSqlDatabaseContainerOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseContainerOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseContainerOperatorSpec) error +} + // Storage version of v1api20210515.ConflictResolutionPolicy // The conflict resolution policy for the container. type ConflictResolutionPolicy struct { diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen_test.go index 10f2194f7c3..a90d7af023b 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_types_gen_test.go @@ -2133,6 +2133,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainer(gens map[string]gopter. gens["Status"] = SqlDatabaseContainer_STATUSGenerator() } +func Test_SqlDatabaseContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerOperatorSpec to SqlDatabaseContainerOperatorSpec via AssignProperties_To_SqlDatabaseContainerOperatorSpec & AssignProperties_From_SqlDatabaseContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec tests if a specific instance of SqlDatabaseContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerOperatorSpecGenerator() +var sqlDatabaseContainerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerOperatorSpecGenerator returns a generator of SqlDatabaseContainerOperatorSpec instances for property testing. +func SqlDatabaseContainerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerOperatorSpecGenerator != nil { + return sqlDatabaseContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerOperatorSpec{}), generators) + + return sqlDatabaseContainerOperatorSpecGenerator +} + func Test_SqlDatabaseContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2376,6 +2473,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[strin // AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlContainerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen.go index 31c67a7812b..4b22661061d 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (function *SqlDatabaseContainerUserDefinedFunction) ConvertTo(hub conversio return function.AssignProperties_To_SqlDatabaseContainerUserDefinedFunction(destination) } +var _ configmaps.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) SecretDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerUserDefinedFunction{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForSqlDatabaseContainerUserDefinedFunction interface { type SqlDatabaseContainerUserDefinedFunction_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerUserDefinedFunctionOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_F // Location function.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + function.OperatorSpec = &operatorSpec + } else { + function.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_T // Location destination.Location = genruntime.ClonePointerToString(function.Location) + // OperatorSpec + if function.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := function.OperatorSpec.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if function.Options != nil { var option storage.CreateUpdateOptions @@ -620,6 +668,136 @@ type augmentConversionForSqlDatabaseContainerUserDefinedFunction_STATUS interfac AssignPropertiesTo(dst *storage.SqlDatabaseContainerUserDefinedFunction_STATUS) error } +// Storage version of v1api20210515.SqlDatabaseContainerUserDefinedFunctionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerUserDefinedFunctionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates our SqlDatabaseContainerUserDefinedFunctionOperatorSpec from the provided source SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates the provided destination SqlDatabaseContainerUserDefinedFunctionOperatorSpec from our SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(destination *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.SqlUserDefinedFunctionGetProperties_Resource_STATUS type SqlUserDefinedFunctionGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` @@ -790,6 +968,11 @@ func (resource *SqlUserDefinedFunctionResource) AssignProperties_To_SqlUserDefin return nil } +type augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error +} + type augmentConversionForSqlUserDefinedFunctionGetProperties_Resource_STATUS interface { AssignPropertiesFrom(src *storage.SqlUserDefinedFunctionGetProperties_Resource_STATUS) error AssignPropertiesTo(dst *storage.SqlUserDefinedFunctionGetProperties_Resource_STATUS) error diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen_test.go index df8e0eb333e..8299183a210 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_container_user_defined_function_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction(gens gens["Status"] = SqlDatabaseContainerUserDefinedFunction_STATUSGenerator() } +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerUserDefinedFunctionOperatorSpec to SqlDatabaseContainerUserDefinedFunctionOperatorSpec via AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec & AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec tests if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerUserDefinedFunctionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() +var sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator returns a generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing. +func SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator != nil { + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpec{}), generators) + + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator +} + func Test_SqlDatabaseContainerUserDefinedFunction_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -407,6 +504,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_ // AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlUserDefinedFunctionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen.go index 6cfea6104d9..f1999809d83 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (setting *SqlDatabaseThroughputSetting) ConvertTo(hub conversion.Hub) error return setting.AssignProperties_To_SqlDatabaseThroughputSetting(destination) } +var _ configmaps.Exporter = &SqlDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForSqlDatabaseThroughputSetting interface { // Storage version of v1api20210515.SqlDatabaseThroughputSetting_Spec type SqlDatabaseThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -303,6 +327,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_From_SqlDatab // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // OriginalVersion setting.OriginalVersion = source.OriginalVersion @@ -357,6 +393,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_To_SqlDatabas // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion @@ -585,6 +633,141 @@ type augmentConversionForSqlDatabaseThroughputSetting_STATUS interface { AssignPropertiesTo(dst *storage.SqlDatabaseThroughputSetting_STATUS) error } +// Storage version of v1api20210515.SqlDatabaseThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec populates our SqlDatabaseThroughputSettingOperatorSpec from the provided source SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec populates the provided destination SqlDatabaseThroughputSettingOperatorSpec from our SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(destination *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseThroughputSettingOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseThroughputSettingOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForSqlDatabaseThroughputSettingOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseThroughputSettingOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseThroughputSettingOperatorSpec) error +} + func init() { SchemeBuilder.Register(&SqlDatabaseThroughputSetting{}, &SqlDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen_test.go index c11f191d344..9a1ea31d83d 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting(gens map[string gens["Status"] = SqlDatabaseThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseThroughputSettingOperatorSpec to SqlDatabaseThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseThroughputSettingOperatorSpecGenerator() +var sqlDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,5 +503,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens m // AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen.go index 97dafcdd7a0..8fbce21eff7 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (database *SqlDatabase) ConvertTo(hub conversion.Hub) error { return database.AssignProperties_To_SqlDatabase(destination) } +var _ configmaps.Exporter = &SqlDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *SqlDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *SqlDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabase{} // AzureName returns the Azure name of the resource @@ -235,10 +258,11 @@ type augmentConversionForSqlDatabase interface { type SqlDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -311,6 +335,18 @@ func (database *SqlDatabase_Spec) AssignProperties_From_SqlDatabase_Spec(source // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -380,6 +416,18 @@ func (database *SqlDatabase_Spec) AssignProperties_To_SqlDatabase_Spec(destinati // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_SqlDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -792,6 +840,136 @@ func (resource *SqlDatabaseGetProperties_Resource_STATUS) AssignProperties_To_Sq return nil } +// Storage version of v1api20210515.SqlDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseOperatorSpec populates our SqlDatabaseOperatorSpec from the provided source SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_From_SqlDatabaseOperatorSpec(source *storage.SqlDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseOperatorSpec populates the provided destination SqlDatabaseOperatorSpec from our SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_To_SqlDatabaseOperatorSpec(destination *storage.SqlDatabaseOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlDatabaseOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlDatabaseOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210515.SqlDatabaseResource // Cosmos DB SQL database resource object type SqlDatabaseResource struct { @@ -900,6 +1078,11 @@ type augmentConversionForSqlDatabaseGetProperties_Resource_STATUS interface { AssignPropertiesTo(dst *storage.SqlDatabaseGetProperties_Resource_STATUS) error } +type augmentConversionForSqlDatabaseOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlDatabaseOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlDatabaseOperatorSpec) error +} + type augmentConversionForSqlDatabaseResource interface { AssignPropertiesFrom(src *storage.SqlDatabaseResource) error AssignPropertiesTo(dst *storage.SqlDatabaseResource) error diff --git a/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen_test.go index 5af0102214b..3ef14eeadef 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_database_types_gen_test.go @@ -272,6 +272,103 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseGetProperties_Resource_STATUS gens["Users"] = gen.PtrOf(gen.AlphaString()) } +func Test_SqlDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseOperatorSpec to SqlDatabaseOperatorSpec via AssignProperties_To_SqlDatabaseOperatorSpec & AssignProperties_From_SqlDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseOperatorSpec tests if a specific instance of SqlDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseOperatorSpec runs a test to see if a specific instance of SqlDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseOperatorSpecGenerator() +var sqlDatabaseOperatorSpecGenerator gopter.Gen + +// SqlDatabaseOperatorSpecGenerator returns a generator of SqlDatabaseOperatorSpec instances for property testing. +func SqlDatabaseOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseOperatorSpecGenerator != nil { + return sqlDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseOperatorSpec{}), generators) + + return sqlDatabaseOperatorSpecGenerator +} + func Test_SqlDatabaseResource_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -616,6 +713,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForSqlDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen.go b/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen.go index 9af09be130a..4c5438e00d2 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/documentdb/v1api20231115/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (assignment *SqlRoleAssignment) ConvertTo(hub conversion.Hub) error { return assignment.AssignProperties_To_SqlRoleAssignment(destination) } +var _ configmaps.Exporter = &SqlRoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *SqlRoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlRoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *SqlRoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlRoleAssignment{} // AzureName returns the Azure name of the resource @@ -235,8 +258,9 @@ type augmentConversionForSqlRoleAssignment interface { type SqlRoleAssignment_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *SqlRoleAssignmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -308,6 +332,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_From_SqlRoleAssignmen // AzureName assignment.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlRoleAssignmentOperatorSpec + err := operatorSpec.AssignProperties_From_SqlRoleAssignmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + assignment.OperatorSpec = &operatorSpec + } else { + assignment.OperatorSpec = nil + } + // OriginalVersion assignment.OriginalVersion = source.OriginalVersion @@ -364,6 +400,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_To_SqlRoleAssignment_ // AzureName destination.AzureName = assignment.AzureName + // OperatorSpec + if assignment.OperatorSpec != nil { + var operatorSpec storage.SqlRoleAssignmentOperatorSpec + err := assignment.OperatorSpec.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = assignment.OriginalVersion @@ -576,6 +624,141 @@ type augmentConversionForSqlRoleAssignment_STATUS interface { AssignPropertiesTo(dst *storage.SqlRoleAssignment_STATUS) error } +// Storage version of v1api20210515.SqlRoleAssignmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlRoleAssignmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlRoleAssignmentOperatorSpec populates our SqlRoleAssignmentOperatorSpec from the provided source SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_From_SqlRoleAssignmentOperatorSpec(source *storage.SqlRoleAssignmentOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlRoleAssignmentOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlRoleAssignmentOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_SqlRoleAssignmentOperatorSpec populates the provided destination SqlRoleAssignmentOperatorSpec from our SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_To_SqlRoleAssignmentOperatorSpec(destination *storage.SqlRoleAssignmentOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForSqlRoleAssignmentOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForSqlRoleAssignmentOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForSqlRoleAssignmentOperatorSpec interface { + AssignPropertiesFrom(src *storage.SqlRoleAssignmentOperatorSpec) error + AssignPropertiesTo(dst *storage.SqlRoleAssignmentOperatorSpec) error +} + func init() { SchemeBuilder.Register(&SqlRoleAssignment{}, &SqlRoleAssignmentList{}) } diff --git a/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen_test.go b/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen_test.go index d48cea63b0e..0dd3e94c598 100644 --- a/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen_test.go +++ b/v2/api/documentdb/v1api20210515/storage/sql_role_assignment_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForSqlRoleAssignment(gens map[string]gopter.Gen gens["Status"] = SqlRoleAssignment_STATUSGenerator() } +func Test_SqlRoleAssignmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlRoleAssignmentOperatorSpec to SqlRoleAssignmentOperatorSpec via AssignProperties_To_SqlRoleAssignmentOperatorSpec & AssignProperties_From_SqlRoleAssignmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec tests if a specific instance of SqlRoleAssignmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlRoleAssignmentOperatorSpec + err := copied.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlRoleAssignmentOperatorSpec + err = actual.AssignProperties_From_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlRoleAssignmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlRoleAssignmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec runs a test to see if a specific instance of SqlRoleAssignmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlRoleAssignmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlRoleAssignmentOperatorSpec instances for property testing - lazily instantiated by +// SqlRoleAssignmentOperatorSpecGenerator() +var sqlRoleAssignmentOperatorSpecGenerator gopter.Gen + +// SqlRoleAssignmentOperatorSpecGenerator returns a generator of SqlRoleAssignmentOperatorSpec instances for property testing. +func SqlRoleAssignmentOperatorSpecGenerator() gopter.Gen { + if sqlRoleAssignmentOperatorSpecGenerator != nil { + return sqlRoleAssignmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlRoleAssignmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignmentOperatorSpec{}), generators) + + return sqlRoleAssignmentOperatorSpecGenerator +} + func Test_SqlRoleAssignment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForSqlRoleAssignment_Spec(subject SqlRoleAssignment var sqlRoleAssignment_SpecGenerator gopter.Gen // SqlRoleAssignment_SpecGenerator returns a generator of SqlRoleAssignment_Spec instances for property testing. +// We first initialize sqlRoleAssignment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func SqlRoleAssignment_SpecGenerator() gopter.Gen { if sqlRoleAssignment_SpecGenerator != nil { return sqlRoleAssignment_SpecGenerator @@ -367,6 +467,12 @@ func SqlRoleAssignment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + return sqlRoleAssignment_SpecGenerator } @@ -378,3 +484,8 @@ func AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]g gens["RoleDefinitionId"] = gen.PtrOf(gen.AlphaString()) gens["Scope"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlRoleAssignmentOperatorSpecGenerator()) +} diff --git a/v2/api/documentdb/v1api20210515/storage/structure.txt b/v2/api/documentdb/v1api20210515/storage/structure.txt index 5be2ec61db3..6422e1e413f 100644 --- a/v2/api/documentdb/v1api20210515/storage/structure.txt +++ b/v2/api/documentdb/v1api20210515/storage/structure.txt @@ -69,8 +69,10 @@ DatabaseAccount: Resource │ │ └── PropertyBag: genruntime.PropertyBag │ ├── NetworkAclBypass: *string │ ├── NetworkAclBypassResourceIds: string[] -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── DocumentEndpoint: *genruntime.SecretDestination │ │ ├── PrimaryMasterKey: *genruntime.SecretDestination @@ -195,9 +197,13 @@ DatabaseAccount: Resource └── ProvisioningState: *string MongodbDatabase: Resource ├── Owner: documentdb/v1api20210515.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -233,9 +239,13 @@ MongodbDatabase: Resource └── Type: *string MongodbDatabaseCollection: Resource ├── Owner: documentdb/v1api20210515.MongodbDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -293,8 +303,12 @@ MongodbDatabaseCollection: Resource └── Type: *string MongodbDatabaseCollectionThroughputSetting: Resource ├── Owner: documentdb/v1api20210515.MongodbDatabaseCollection -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -339,8 +353,12 @@ MongodbDatabaseCollectionThroughputSetting: Resource └── Type: *string MongodbDatabaseThroughputSetting: Resource ├── Owner: documentdb/v1api20210515.MongodbDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -385,9 +403,13 @@ MongodbDatabaseThroughputSetting: Resource └── Type: *string SqlDatabase: Resource ├── Owner: documentdb/v1api20210515.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -425,9 +447,13 @@ SqlDatabase: Resource └── Type: *string SqlDatabaseContainer: Resource ├── Owner: documentdb/v1api20210515.SqlDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -544,9 +570,13 @@ SqlDatabaseContainer: Resource └── Type: *string SqlDatabaseContainerStoredProcedure: Resource ├── Owner: documentdb/v1api20210515.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -578,8 +608,12 @@ SqlDatabaseContainerStoredProcedure: Resource └── Type: *string SqlDatabaseContainerThroughputSetting: Resource ├── Owner: documentdb/v1api20210515.SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -624,9 +658,13 @@ SqlDatabaseContainerThroughputSetting: Resource └── Type: *string SqlDatabaseContainerTrigger: Resource ├── Owner: documentdb/v1api20210515.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -662,9 +700,13 @@ SqlDatabaseContainerTrigger: Resource └── Type: *string SqlDatabaseContainerUserDefinedFunction: Resource ├── Owner: documentdb/v1api20210515.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -696,8 +738,12 @@ SqlDatabaseContainerUserDefinedFunction: Resource └── Type: *string SqlDatabaseThroughputSetting: Resource ├── Owner: documentdb/v1api20210515.SqlDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -742,8 +788,12 @@ SqlDatabaseThroughputSetting: Resource └── Type: *string SqlRoleAssignment: Resource ├── Owner: documentdb/v1api20210515.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrincipalId: *string @@ -820,12 +870,16 @@ augmentConversionForMongoIndexOptions_STATUS: Interface augmentConversionForMongoIndex_STATUS: Interface augmentConversionForMongodbDatabase: Interface augmentConversionForMongodbDatabaseCollection: Interface +augmentConversionForMongodbDatabaseCollectionOperatorSpec: Interface augmentConversionForMongodbDatabaseCollectionThroughputSetting: Interface +augmentConversionForMongodbDatabaseCollectionThroughputSettingOperatorSpec: Interface augmentConversionForMongodbDatabaseCollectionThroughputSetting_STATUS: Interface augmentConversionForMongodbDatabaseCollectionThroughputSetting_Spec: Interface augmentConversionForMongodbDatabaseCollection_STATUS: Interface augmentConversionForMongodbDatabaseCollection_Spec: Interface +augmentConversionForMongodbDatabaseOperatorSpec: Interface augmentConversionForMongodbDatabaseThroughputSetting: Interface +augmentConversionForMongodbDatabaseThroughputSettingOperatorSpec: Interface augmentConversionForMongodbDatabaseThroughputSetting_STATUS: Interface augmentConversionForMongodbDatabaseThroughputSetting_Spec: Interface augmentConversionForMongodbDatabase_STATUS: Interface @@ -842,28 +896,36 @@ augmentConversionForSqlContainerGetProperties_Resource_STATUS: Interface augmentConversionForSqlContainerResource: Interface augmentConversionForSqlDatabase: Interface augmentConversionForSqlDatabaseContainer: Interface +augmentConversionForSqlDatabaseContainerOperatorSpec: Interface augmentConversionForSqlDatabaseContainerStoredProcedure: Interface +augmentConversionForSqlDatabaseContainerStoredProcedureOperatorSpec: Interface augmentConversionForSqlDatabaseContainerStoredProcedure_STATUS: Interface augmentConversionForSqlDatabaseContainerStoredProcedure_Spec: Interface augmentConversionForSqlDatabaseContainerThroughputSetting: Interface +augmentConversionForSqlDatabaseContainerThroughputSettingOperatorSpec: Interface augmentConversionForSqlDatabaseContainerThroughputSetting_STATUS: Interface augmentConversionForSqlDatabaseContainerThroughputSetting_Spec: Interface augmentConversionForSqlDatabaseContainerTrigger: Interface +augmentConversionForSqlDatabaseContainerTriggerOperatorSpec: Interface augmentConversionForSqlDatabaseContainerTrigger_STATUS: Interface augmentConversionForSqlDatabaseContainerTrigger_Spec: Interface augmentConversionForSqlDatabaseContainerUserDefinedFunction: Interface +augmentConversionForSqlDatabaseContainerUserDefinedFunctionOperatorSpec: Interface augmentConversionForSqlDatabaseContainerUserDefinedFunction_STATUS: Interface augmentConversionForSqlDatabaseContainerUserDefinedFunction_Spec: Interface augmentConversionForSqlDatabaseContainer_STATUS: Interface augmentConversionForSqlDatabaseContainer_Spec: Interface augmentConversionForSqlDatabaseGetProperties_Resource_STATUS: Interface +augmentConversionForSqlDatabaseOperatorSpec: Interface augmentConversionForSqlDatabaseResource: Interface augmentConversionForSqlDatabaseThroughputSetting: Interface +augmentConversionForSqlDatabaseThroughputSettingOperatorSpec: Interface augmentConversionForSqlDatabaseThroughputSetting_STATUS: Interface augmentConversionForSqlDatabaseThroughputSetting_Spec: Interface augmentConversionForSqlDatabase_STATUS: Interface augmentConversionForSqlDatabase_Spec: Interface augmentConversionForSqlRoleAssignment: Interface +augmentConversionForSqlRoleAssignmentOperatorSpec: Interface augmentConversionForSqlRoleAssignment_STATUS: Interface augmentConversionForSqlRoleAssignment_Spec: Interface augmentConversionForSqlStoredProcedureGetProperties_Resource_STATUS: Interface diff --git a/v2/api/documentdb/v1api20210515/storage/zz_generated.deepcopy.go b/v2/api/documentdb/v1api20210515/storage/zz_generated.deepcopy.go index 4e442ee9f71..7fbc28f9629 100644 --- a/v2/api/documentdb/v1api20210515/storage/zz_generated.deepcopy.go +++ b/v2/api/documentdb/v1api20210515/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -998,6 +999,17 @@ func (in *DatabaseAccountOperatorSecrets) DeepCopy() *DatabaseAccountOperatorSec // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -1005,6 +1017,17 @@ func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperator (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(DatabaseAccountOperatorSecrets) @@ -2492,6 +2515,50 @@ func (in *MongodbDatabaseCollectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionOperatorSpec. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopy() *MongodbDatabaseCollectionOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting) { *out = *in @@ -2551,6 +2618,50 @@ func (in *MongodbDatabaseCollectionThroughputSettingList) DeepCopyObject() runti return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionThroughputSettingOperatorSpec. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseCollectionThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting_STATUS) { *out = *in @@ -2620,6 +2731,11 @@ func (in *MongodbDatabaseCollectionThroughputSetting_Spec) DeepCopyInto(out *Mon *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2730,6 +2846,11 @@ func (in *MongodbDatabaseCollection_Spec) DeepCopyInto(out *MongodbDatabaseColle *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -2803,6 +2924,50 @@ func (in *MongodbDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseOperatorSpec) DeepCopyInto(out *MongodbDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseOperatorSpec. +func (in *MongodbDatabaseOperatorSpec) DeepCopy() *MongodbDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting) DeepCopyInto(out *MongodbDatabaseThroughputSetting) { *out = *in @@ -2862,6 +3027,50 @@ func (in *MongodbDatabaseThroughputSettingList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseThroughputSettingOperatorSpec. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseThroughputSetting_STATUS) { *out = *in @@ -2931,6 +3140,11 @@ func (in *MongodbDatabaseThroughputSetting_Spec) DeepCopyInto(out *MongodbDataba *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3041,6 +3255,11 @@ func (in *MongodbDatabase_Spec) DeepCopyInto(out *MongodbDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3548,6 +3767,50 @@ func (in *SqlDatabaseContainerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerOperatorSpec. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopy() *SqlDatabaseContainerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure) { *out = *in @@ -3607,6 +3870,50 @@ func (in *SqlDatabaseContainerStoredProcedureList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerStoredProcedureOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerStoredProcedureOperatorSpec. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopy() *SqlDatabaseContainerStoredProcedureOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerStoredProcedureOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure_STATUS) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure_STATUS) { *out = *in @@ -3676,6 +3983,11 @@ func (in *SqlDatabaseContainerStoredProcedure_Spec) DeepCopyInto(out *SqlDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerStoredProcedureOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3776,6 +4088,50 @@ func (in *SqlDatabaseContainerThroughputSettingList) DeepCopyObject() runtime.Ob return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerThroughputSettingOperatorSpec. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseContainerThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseContainerThroughputSetting_STATUS) { *out = *in @@ -3845,6 +4201,11 @@ func (in *SqlDatabaseContainerThroughputSetting_Spec) DeepCopyInto(out *SqlDatab *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3940,6 +4301,50 @@ func (in *SqlDatabaseContainerTriggerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerTriggerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerTriggerOperatorSpec. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopy() *SqlDatabaseContainerTriggerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerTriggerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerTrigger_STATUS) DeepCopyInto(out *SqlDatabaseContainerTrigger_STATUS) { *out = *in @@ -4009,6 +4414,11 @@ func (in *SqlDatabaseContainerTrigger_Spec) DeepCopyInto(out *SqlDatabaseContain *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerTriggerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4109,6 +4519,50 @@ func (in *SqlDatabaseContainerUserDefinedFunctionList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerUserDefinedFunctionOperatorSpec. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopy() *SqlDatabaseContainerUserDefinedFunctionOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerUserDefinedFunction_STATUS) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunction_STATUS) { *out = *in @@ -4178,6 +4632,11 @@ func (in *SqlDatabaseContainerUserDefinedFunction_Spec) DeepCopyInto(out *SqlDat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4293,6 +4752,11 @@ func (in *SqlDatabaseContainer_Spec) DeepCopyInto(out *SqlDatabaseContainer_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4418,6 +4882,50 @@ func (in *SqlDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseOperatorSpec) DeepCopyInto(out *SqlDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseOperatorSpec. +func (in *SqlDatabaseOperatorSpec) DeepCopy() *SqlDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseResource) DeepCopyInto(out *SqlDatabaseResource) { *out = *in @@ -4504,6 +5012,50 @@ func (in *SqlDatabaseThroughputSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseThroughputSettingOperatorSpec. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseThroughputSetting_STATUS) { *out = *in @@ -4573,6 +5125,11 @@ func (in *SqlDatabaseThroughputSetting_Spec) DeepCopyInto(out *SqlDatabaseThroug *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4683,6 +5240,11 @@ func (in *SqlDatabase_Spec) DeepCopyInto(out *SqlDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4783,6 +5345,50 @@ func (in *SqlRoleAssignmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopyInto(out *SqlRoleAssignmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlRoleAssignmentOperatorSpec. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopy() *SqlRoleAssignmentOperatorSpec { + if in == nil { + return nil + } + out := new(SqlRoleAssignmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_STATUS) DeepCopyInto(out *SqlRoleAssignment_STATUS) { *out = *in @@ -4845,6 +5451,11 @@ func (in *SqlRoleAssignment_STATUS) DeepCopy() *SqlRoleAssignment_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_Spec) DeepCopyInto(out *SqlRoleAssignment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlRoleAssignmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/documentdb/v1api20210515/structure.txt b/v2/api/documentdb/v1api20210515/structure.txt index b98f1fa335f..b658737f2e0 100644 --- a/v2/api/documentdb/v1api20210515/structure.txt +++ b/v2/api/documentdb/v1api20210515/structure.txt @@ -91,7 +91,9 @@ DatabaseAccount: Resource │ │ ├── "AzureServices" │ │ └── "None" │ ├── NetworkAclBypassResourceIds: string[] -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── DocumentEndpoint: *genruntime.SecretDestination │ │ ├── PrimaryMasterKey: *genruntime.SecretDestination @@ -220,9 +222,12 @@ DatabaseAccount: Resource └── ProvisioningState: *string MongodbDatabase: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -249,9 +254,12 @@ MongodbDatabase: Resource └── Type: *string MongodbDatabaseCollection: Resource ├── Owner: MongodbDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -294,8 +302,11 @@ MongodbDatabaseCollection: Resource └── Type: *string MongodbDatabaseCollectionThroughputSetting: Resource ├── Owner: MongodbDatabaseCollection -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -329,8 +340,11 @@ MongodbDatabaseCollectionThroughputSetting: Resource └── Type: *string MongodbDatabaseThroughputSetting: Resource ├── Owner: MongodbDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -364,9 +378,12 @@ MongodbDatabaseThroughputSetting: Resource └── Type: *string SqlDatabase: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -395,9 +412,12 @@ SqlDatabase: Resource └── Type: *string SqlDatabaseContainer: Resource ├── Owner: SqlDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -533,9 +553,12 @@ SqlDatabaseContainer: Resource └── Type: *string SqlDatabaseContainerStoredProcedure: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -560,8 +583,11 @@ SqlDatabaseContainerStoredProcedure: Resource └── Type: *string SqlDatabaseContainerThroughputSetting: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -595,9 +621,12 @@ SqlDatabaseContainerThroughputSetting: Resource └── Type: *string SqlDatabaseContainerTrigger: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -640,9 +669,12 @@ SqlDatabaseContainerTrigger: Resource └── Type: *string SqlDatabaseContainerUserDefinedFunction: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -667,8 +699,11 @@ SqlDatabaseContainerUserDefinedFunction: Resource └── Type: *string SqlDatabaseThroughputSetting: Resource ├── Owner: SqlDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -702,8 +737,11 @@ SqlDatabaseThroughputSetting: Resource └── Type: *string SqlRoleAssignment: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrincipalId: *string │ ├── PrincipalIdFromConfig: *genruntime.ConfigMapReference diff --git a/v2/api/documentdb/v1api20210515/zz_generated.deepcopy.go b/v2/api/documentdb/v1api20210515/zz_generated.deepcopy.go index e2b52d57044..f9209603270 100644 --- a/v2/api/documentdb/v1api20210515/zz_generated.deepcopy.go +++ b/v2/api/documentdb/v1api20210515/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210515 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -802,6 +803,28 @@ func (in *DatabaseAccountOperatorSecrets) DeepCopy() *DatabaseAccountOperatorSec // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(DatabaseAccountOperatorSecrets) @@ -2091,6 +2114,43 @@ func (in *MongodbDatabaseCollectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionOperatorSpec. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopy() *MongodbDatabaseCollectionOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting) { *out = *in @@ -2150,6 +2210,43 @@ func (in *MongodbDatabaseCollectionThroughputSettingList) DeepCopyObject() runti return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionThroughputSettingOperatorSpec. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseCollectionThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting_STATUS) { *out = *in @@ -2212,6 +2309,11 @@ func (in *MongodbDatabaseCollectionThroughputSetting_Spec) DeepCopyInto(out *Mon *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2308,6 +2410,11 @@ func (in *MongodbDatabaseCollection_Spec) DeepCopyInto(out *MongodbDatabaseColle *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -2374,6 +2481,43 @@ func (in *MongodbDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseOperatorSpec) DeepCopyInto(out *MongodbDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseOperatorSpec. +func (in *MongodbDatabaseOperatorSpec) DeepCopy() *MongodbDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting) DeepCopyInto(out *MongodbDatabaseThroughputSetting) { *out = *in @@ -2433,6 +2577,43 @@ func (in *MongodbDatabaseThroughputSettingList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseThroughputSettingOperatorSpec. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseThroughputSetting_STATUS) { *out = *in @@ -2495,6 +2676,11 @@ func (in *MongodbDatabaseThroughputSetting_Spec) DeepCopyInto(out *MongodbDataba *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2591,6 +2777,11 @@ func (in *MongodbDatabase_Spec) DeepCopyInto(out *MongodbDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3021,6 +3212,43 @@ func (in *SqlDatabaseContainerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerOperatorSpec. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopy() *SqlDatabaseContainerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure) { *out = *in @@ -3080,6 +3308,43 @@ func (in *SqlDatabaseContainerStoredProcedureList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerStoredProcedureOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerStoredProcedureOperatorSpec. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopy() *SqlDatabaseContainerStoredProcedureOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerStoredProcedureOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure_STATUS) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure_STATUS) { *out = *in @@ -3142,6 +3407,11 @@ func (in *SqlDatabaseContainerStoredProcedure_Spec) DeepCopyInto(out *SqlDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerStoredProcedureOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3235,6 +3505,43 @@ func (in *SqlDatabaseContainerThroughputSettingList) DeepCopyObject() runtime.Ob return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerThroughputSettingOperatorSpec. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseContainerThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseContainerThroughputSetting_STATUS) { *out = *in @@ -3297,6 +3604,11 @@ func (in *SqlDatabaseContainerThroughputSetting_Spec) DeepCopyInto(out *SqlDatab *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3385,6 +3697,43 @@ func (in *SqlDatabaseContainerTriggerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerTriggerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerTriggerOperatorSpec. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopy() *SqlDatabaseContainerTriggerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerTriggerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerTrigger_STATUS) DeepCopyInto(out *SqlDatabaseContainerTrigger_STATUS) { *out = *in @@ -3447,6 +3796,11 @@ func (in *SqlDatabaseContainerTrigger_Spec) DeepCopyInto(out *SqlDatabaseContain *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerTriggerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3540,6 +3894,43 @@ func (in *SqlDatabaseContainerUserDefinedFunctionList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerUserDefinedFunctionOperatorSpec. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopy() *SqlDatabaseContainerUserDefinedFunctionOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerUserDefinedFunction_STATUS) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunction_STATUS) { *out = *in @@ -3602,6 +3993,11 @@ func (in *SqlDatabaseContainerUserDefinedFunction_Spec) DeepCopyInto(out *SqlDat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3703,6 +4099,11 @@ func (in *SqlDatabaseContainer_Spec) DeepCopyInto(out *SqlDatabaseContainer_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3814,6 +4215,43 @@ func (in *SqlDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseOperatorSpec) DeepCopyInto(out *SqlDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseOperatorSpec. +func (in *SqlDatabaseOperatorSpec) DeepCopy() *SqlDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseResource) DeepCopyInto(out *SqlDatabaseResource) { *out = *in @@ -3893,6 +4331,43 @@ func (in *SqlDatabaseThroughputSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseThroughputSettingOperatorSpec. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseThroughputSetting_STATUS) { *out = *in @@ -3955,6 +4430,11 @@ func (in *SqlDatabaseThroughputSetting_Spec) DeepCopyInto(out *SqlDatabaseThroug *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4051,6 +4531,11 @@ func (in *SqlDatabase_Spec) DeepCopyInto(out *SqlDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4144,6 +4629,43 @@ func (in *SqlRoleAssignmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopyInto(out *SqlRoleAssignmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlRoleAssignmentOperatorSpec. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopy() *SqlRoleAssignmentOperatorSpec { + if in == nil { + return nil + } + out := new(SqlRoleAssignmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_STATUS) DeepCopyInto(out *SqlRoleAssignment_STATUS) { *out = *in @@ -4199,6 +4721,11 @@ func (in *SqlRoleAssignment_STATUS) DeepCopy() *SqlRoleAssignment_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_Spec) DeepCopyInto(out *SqlRoleAssignment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlRoleAssignmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/documentdb/v1api20231115/database_account_types_gen.go b/v2/api/documentdb/v1api20231115/database_account_types_gen.go index cd7466839bc..e8ad8f92c91 100644 --- a/v2/api/documentdb/v1api20231115/database_account_types_gen.go +++ b/v2/api/documentdb/v1api20231115/database_account_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (account *DatabaseAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the DatabaseAccount resource func (account *DatabaseAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &DatabaseAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *DatabaseAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DatabaseAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *DatabaseAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DatabaseAccount{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (account *DatabaseAccount) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (account *DatabaseAccount) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations} + return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations, account.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (account *DatabaseAccount) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return account.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (account *DatabaseAccount) validateConfigMapDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(account, nil, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,17 +286,17 @@ func (account *DatabaseAccount) validateSecretDestinations() (admission.Warnings if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - account.Spec.OperatorSpec.Secrets.DocumentEndpoint, - account.Spec.OperatorSpec.Secrets.PrimaryMasterKey, - account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, - account.Spec.OperatorSpec.Secrets.SecondaryMasterKey, - account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, + var toValidate []*genruntime.SecretDestination + if account.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + account.Spec.OperatorSpec.Secrets.DocumentEndpoint, + account.Spec.OperatorSpec.Secrets.PrimaryMasterKey, + account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, + account.Spec.OperatorSpec.Secrets.SecondaryMasterKey, + account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -5786,6 +5819,12 @@ var databaseAccountOfferType_STATUS_Values = map[string]DatabaseAccountOfferType // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type DatabaseAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` } @@ -5793,6 +5832,42 @@ type DatabaseAccountOperatorSpec struct { // AssignProperties_From_DatabaseAccountOperatorSpec populates our DatabaseAccountOperatorSpec from the provided source DatabaseAccountOperatorSpec func (operator *DatabaseAccountOperatorSpec) AssignProperties_From_DatabaseAccountOperatorSpec(source *storage.DatabaseAccountOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret DatabaseAccountOperatorSecrets @@ -5814,6 +5889,42 @@ func (operator *DatabaseAccountOperatorSpec) AssignProperties_To_DatabaseAccount // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.DatabaseAccountOperatorSecrets diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen.go index 830c599d926..01e2d43b72f 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the MongodbDatabaseCollectionThroughputSetting resource func (setting *MongodbDatabaseCollectionThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MongodbDatabaseCollectionThroughputSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) ValidateUpdate(old ru // createValidations validates the creation of the resource func (setting *MongodbDatabaseCollectionThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) updateValidations() [ func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *MongodbDatabaseCollectionThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) validateResourceRefer return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *MongodbDatabaseCollectionThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *MongodbDatabaseCollectionThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseCollectionThroughputSetting) @@ -321,6 +366,10 @@ type MongodbDatabaseCollectionThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseCollectionThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -392,6 +441,8 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) PopulateFromARM( setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -480,6 +531,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -515,6 +578,18 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_Spec) AssignProperties // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -800,6 +875,110 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_STATUS) AssignProperti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates our MongodbDatabaseCollectionThroughputSettingOperatorSpec from the provided source MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(source *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseCollectionThroughputSettingOperatorSpec from our MongodbDatabaseCollectionThroughputSettingOperatorSpec +func (operator *MongodbDatabaseCollectionThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ThroughputSettingsGetProperties_Resource_STATUS struct { // AutoscaleSettings: Cosmos DB resource for autoscale settings. Either throughput is required or autoscaleSettings is // required, but not both. diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen_test.go index 4c290763d59..55b07e92aa5 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_collection_throughput_setting_types_gen_test.go @@ -606,6 +606,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting(g gens["Status"] = MongodbDatabaseCollectionThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionThroughputSettingOperatorSpec to MongodbDatabaseCollectionThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseCollectionThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing - lazily +// instantiated by MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseCollectionThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -846,6 +943,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetti // AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen.go b/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen.go index b76773c5094..8794341efbe 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (collection *MongodbDatabaseCollection) defaultAzureName() { // defaultImpl applies the code generated defaults to the MongodbDatabaseCollection resource func (collection *MongodbDatabaseCollection) defaultImpl() { collection.defaultAzureName() } +var _ configmaps.Exporter = &MongodbDatabaseCollection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (collection *MongodbDatabaseCollection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (collection *MongodbDatabaseCollection) SecretDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MongodbDatabaseCollection{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (collection *MongodbDatabaseCollection) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (collection *MongodbDatabaseCollection) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){collection.validateResourceReferences, collection.validateOwnerReference} + return []func() (admission.Warnings, error){collection.validateResourceReferences, collection.validateOwnerReference, collection.validateSecretDestinations, collection.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (collection *MongodbDatabaseCollection) updateValidations() []func(old runt func(old runtime.Object) (admission.Warnings, error) { return collection.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return collection.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return collection.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (collection *MongodbDatabaseCollection) validateConfigMapDestinations() (admission.Warnings, error) { + if collection.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(collection, nil, collection.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (collection *MongodbDatabaseCollection) validateResourceReferences() (admis return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (collection *MongodbDatabaseCollection) validateSecretDestinations() (admission.Warnings, error) { + if collection.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(collection, nil, collection.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (collection *MongodbDatabaseCollection) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseCollection) @@ -333,6 +378,10 @@ type MongodbDatabaseCollection_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseCollectionOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (collection *MongodbDatabaseCollection_Spec) PopulateFromARM(owner genrunti collection.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_From_MongodbD // Location collection.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseCollectionOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + collection.OperatorSpec = &operatorSpec + } else { + collection.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (collection *MongodbDatabaseCollection_Spec) AssignProperties_To_MongodbDat // Location destination.Location = genruntime.ClonePointerToString(collection.Location) + // OperatorSpec + if collection.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseCollectionOperatorSpec + err := collection.OperatorSpec.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseCollectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if collection.Options != nil { var option storage.CreateUpdateOptions @@ -1506,6 +1581,110 @@ func (resource *MongoDBCollectionResource) Initialize_From_MongoDBCollectionGetP return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseCollectionOperatorSpec populates our MongodbDatabaseCollectionOperatorSpec from the provided source MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(source *storage.MongodbDatabaseCollectionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseCollectionOperatorSpec populates the provided destination MongodbDatabaseCollectionOperatorSpec from our MongodbDatabaseCollectionOperatorSpec +func (operator *MongodbDatabaseCollectionOperatorSpec) AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(destination *storage.MongodbDatabaseCollectionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB MongoDB collection index key type MongoIndex struct { // Key: Cosmos DB MongoDB collection index keys diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen_test.go b/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen_test.go index d35a6b97307..44107a86e01 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_collection_types_gen_test.go @@ -1032,6 +1032,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection(gens map[string]go gens["Status"] = MongodbDatabaseCollection_STATUSGenerator() } +func Test_MongodbDatabaseCollectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseCollectionOperatorSpec to MongodbDatabaseCollectionOperatorSpec via AssignProperties_To_MongodbDatabaseCollectionOperatorSpec & AssignProperties_From_MongodbDatabaseCollectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec tests if a specific instance of MongodbDatabaseCollectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseCollectionOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseCollectionOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseCollectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseCollectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseCollectionOperatorSpecGenerator() +var mongodbDatabaseCollectionOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionOperatorSpec instances for property testing. +func MongodbDatabaseCollectionOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionOperatorSpec{}), generators) + + return mongodbDatabaseCollectionOperatorSpecGenerator +} + func Test_MongodbDatabaseCollection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1274,6 +1371,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[ // AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBCollectionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen.go index ef39136ebae..4dc5b15b7d3 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *MongodbDatabaseThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the MongodbDatabaseThroughputSetting resource func (setting *MongodbDatabaseThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &MongodbDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MongodbDatabaseThroughputSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *MongodbDatabaseThroughputSetting) ValidateUpdate(old runtime.Obje // createValidations validates the creation of the resource func (setting *MongodbDatabaseThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *MongodbDatabaseThroughputSetting) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *MongodbDatabaseThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *MongodbDatabaseThroughputSetting) validateResourceReferences() (a return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *MongodbDatabaseThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *MongodbDatabaseThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabaseThroughputSetting) @@ -321,6 +366,10 @@ type MongodbDatabaseThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -392,6 +441,8 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) PopulateFromARM(owner genr setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -480,6 +531,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_From_Mong // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -515,6 +578,18 @@ func (setting *MongodbDatabaseThroughputSetting_Spec) AssignProperties_To_Mongod // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -800,6 +875,110 @@ func (setting *MongodbDatabaseThroughputSetting_STATUS) AssignProperties_To_Mong return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec populates our MongodbDatabaseThroughputSettingOperatorSpec from the provided source MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(source *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec populates the provided destination MongodbDatabaseThroughputSettingOperatorSpec from our MongodbDatabaseThroughputSettingOperatorSpec +func (operator *MongodbDatabaseThroughputSettingOperatorSpec) AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(destination *storage.MongodbDatabaseThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&MongodbDatabaseThroughputSetting{}, &MongodbDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen_test.go index 7d037635710..e18f7521ec0 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting(gens map[st gens["Status"] = MongodbDatabaseThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseThroughputSettingOperatorSpec to MongodbDatabaseThroughputSettingOperatorSpec via AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec & AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec tests if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -405,5 +502,6 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(ge // AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_types_gen.go b/v2/api/documentdb/v1api20231115/mongodb_database_types_gen.go index 57143e8770d..cb5374aba8d 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_types_gen.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *MongodbDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the MongodbDatabase resource func (database *MongodbDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &MongodbDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *MongodbDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *MongodbDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MongodbDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *MongodbDatabase) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (database *MongodbDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *MongodbDatabase) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *MongodbDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *MongodbDatabase) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *MongodbDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *MongodbDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MongodbDatabase) @@ -333,6 +378,10 @@ type MongodbDatabase_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MongodbDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (database *MongodbDatabase_Spec) PopulateFromARM(owner genruntime.Arbitrary database.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_From_MongodbDatabase_Spec // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MongodbDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_MongodbDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (database *MongodbDatabase_Spec) AssignProperties_To_MongodbDatabase_Spec(d // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.MongodbDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_MongodbDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MongodbDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -1252,6 +1327,110 @@ func (resource *MongoDBDatabaseGetProperties_Resource_STATUS) AssignProperties_T return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MongodbDatabaseOperatorSpec populates our MongodbDatabaseOperatorSpec from the provided source MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_From_MongodbDatabaseOperatorSpec(source *storage.MongodbDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MongodbDatabaseOperatorSpec populates the provided destination MongodbDatabaseOperatorSpec from our MongodbDatabaseOperatorSpec +func (operator *MongodbDatabaseOperatorSpec) AssignProperties_To_MongodbDatabaseOperatorSpec(destination *storage.MongodbDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB MongoDB database resource object type MongoDBDatabaseResource struct { // CreateMode: Enum to indicate the mode of resource creation. diff --git a/v2/api/documentdb/v1api20231115/mongodb_database_types_gen_test.go b/v2/api/documentdb/v1api20231115/mongodb_database_types_gen_test.go index 7b0f1ff391c..1e2183f99ac 100644 --- a/v2/api/documentdb/v1api20231115/mongodb_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/mongodb_database_types_gen_test.go @@ -725,6 +725,103 @@ func AddRelatedPropertyGeneratorsForMongodbDatabase(gens map[string]gopter.Gen) gens["Status"] = MongodbDatabase_STATUSGenerator() } +func Test_MongodbDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MongodbDatabaseOperatorSpec to MongodbDatabaseOperatorSpec via AssignProperties_To_MongodbDatabaseOperatorSpec & AssignProperties_From_MongodbDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec tests if a specific instance of MongodbDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MongodbDatabaseOperatorSpec + err := copied.AssignProperties_To_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MongodbDatabaseOperatorSpec + err = actual.AssignProperties_From_MongodbDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MongodbDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseOperatorSpec runs a test to see if a specific instance of MongodbDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseOperatorSpecGenerator() +var mongodbDatabaseOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseOperatorSpecGenerator returns a generator of MongodbDatabaseOperatorSpec instances for property testing. +func MongodbDatabaseOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseOperatorSpecGenerator != nil { + return mongodbDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseOperatorSpec{}), generators) + + return mongodbDatabaseOperatorSpecGenerator +} + func Test_MongodbDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -967,6 +1064,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForMongodbDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen.go index 8a7b60ad6a1..7cadf6ec398 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (procedure *SqlDatabaseContainerStoredProcedure) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerStoredProcedure resource func (procedure *SqlDatabaseContainerStoredProcedure) defaultImpl() { procedure.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) SecretDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseContainerStoredProcedure{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (procedure *SqlDatabaseContainerStoredProcedure) ValidateUpdate(old runtime // createValidations validates the creation of the resource func (procedure *SqlDatabaseContainerStoredProcedure) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){procedure.validateResourceReferences, procedure.validateOwnerReference} + return []func() (admission.Warnings, error){procedure.validateResourceReferences, procedure.validateOwnerReference, procedure.validateSecretDestinations, procedure.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (procedure *SqlDatabaseContainerStoredProcedure) updateValidations() []func func(old runtime.Object) (admission.Warnings, error) { return procedure.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return procedure.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return procedure.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (procedure *SqlDatabaseContainerStoredProcedure) validateConfigMapDestinations() (admission.Warnings, error) { + if procedure.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(procedure, nil, procedure.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (procedure *SqlDatabaseContainerStoredProcedure) validateResourceReferences return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (procedure *SqlDatabaseContainerStoredProcedure) validateSecretDestinations() (admission.Warnings, error) { + if procedure.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(procedure, nil, procedure.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (procedure *SqlDatabaseContainerStoredProcedure) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerStoredProcedure) @@ -333,6 +378,10 @@ type SqlDatabaseContainerStoredProcedure_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerStoredProcedureOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) PopulateFromARM(owner procedure.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_From // Location procedure.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerStoredProcedureOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + procedure.OperatorSpec = &operatorSpec + } else { + procedure.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (procedure *SqlDatabaseContainerStoredProcedure_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(procedure.Location) + // OperatorSpec + if procedure.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerStoredProcedureOperatorSpec + err := procedure.OperatorSpec.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if procedure.Options != nil { var option storage.CreateUpdateOptions @@ -876,6 +951,110 @@ func (procedure *SqlDatabaseContainerStoredProcedure_STATUS) AssignProperties_To return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerStoredProcedureOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec populates our SqlDatabaseContainerStoredProcedureOperatorSpec from the provided source SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(source *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec populates the provided destination SqlDatabaseContainerStoredProcedureOperatorSpec from our SqlDatabaseContainerStoredProcedureOperatorSpec +func (operator *SqlDatabaseContainerStoredProcedureOperatorSpec) AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(destination *storage.SqlDatabaseContainerStoredProcedureOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlStoredProcedureGetProperties_Resource_STATUS struct { // Body: Body of the Stored Procedure Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen_test.go index b197cd32e02..d49fe88123d 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_stored_procedure_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure(gens map gens["Status"] = SqlDatabaseContainerStoredProcedure_STATUSGenerator() } +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerStoredProcedureOperatorSpec to SqlDatabaseContainerStoredProcedureOperatorSpec via AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec & AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec tests if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerStoredProcedureOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerStoredProcedureOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerStoredProcedureOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() +var sqlDatabaseContainerStoredProcedureOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator returns a generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing. +func SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerStoredProcedureOperatorSpecGenerator != nil { + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerStoredProcedureOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerStoredProcedureOperatorSpec{}), generators) + + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator +} + func Test_SqlDatabaseContainerStoredProcedure_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,6 +503,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec // AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerStoredProcedureOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlStoredProcedureResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen.go index c401a244e4e..43f750d08ab 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *SqlDatabaseContainerThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerThroughputSetting resource func (setting *SqlDatabaseContainerThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseContainerThroughputSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *SqlDatabaseContainerThroughputSetting) ValidateUpdate(old runtime // createValidations validates the creation of the resource func (setting *SqlDatabaseContainerThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *SqlDatabaseContainerThroughputSetting) updateValidations() []func func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *SqlDatabaseContainerThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *SqlDatabaseContainerThroughputSetting) validateResourceReferences return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *SqlDatabaseContainerThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *SqlDatabaseContainerThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerThroughputSetting) @@ -321,6 +366,10 @@ type SqlDatabaseContainerThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -392,6 +441,8 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) PopulateFromARM(owner setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -480,6 +531,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_From // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -515,6 +578,18 @@ func (setting *SqlDatabaseContainerThroughputSetting_Spec) AssignProperties_To_S // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -800,6 +875,110 @@ func (setting *SqlDatabaseContainerThroughputSetting_STATUS) AssignProperties_To return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec populates our SqlDatabaseContainerThroughputSettingOperatorSpec from the provided source SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(source *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec populates the provided destination SqlDatabaseContainerThroughputSettingOperatorSpec from our SqlDatabaseContainerThroughputSettingOperatorSpec +func (operator *SqlDatabaseContainerThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(destination *storage.SqlDatabaseContainerThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlDatabaseContainerThroughputSetting{}, &SqlDatabaseContainerThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen_test.go index 1de640b318e..d830ed4672f 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting(gens m gens["Status"] = SqlDatabaseContainerThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerThroughputSettingOperatorSpec to SqlDatabaseContainerThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() +var sqlDatabaseContainerThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseContainerThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -405,5 +502,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Sp // AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen.go index 3c01407fc5e..7162582869e 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (trigger *SqlDatabaseContainerTrigger) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerTrigger resource func (trigger *SqlDatabaseContainerTrigger) defaultImpl() { trigger.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerTrigger{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (trigger *SqlDatabaseContainerTrigger) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerTrigger{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (trigger *SqlDatabaseContainerTrigger) SecretDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseContainerTrigger{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (trigger *SqlDatabaseContainerTrigger) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (trigger *SqlDatabaseContainerTrigger) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){trigger.validateResourceReferences, trigger.validateOwnerReference} + return []func() (admission.Warnings, error){trigger.validateResourceReferences, trigger.validateOwnerReference, trigger.validateSecretDestinations, trigger.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (trigger *SqlDatabaseContainerTrigger) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return trigger.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return trigger.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return trigger.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (trigger *SqlDatabaseContainerTrigger) validateConfigMapDestinations() (admission.Warnings, error) { + if trigger.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(trigger, nil, trigger.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (trigger *SqlDatabaseContainerTrigger) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (trigger *SqlDatabaseContainerTrigger) validateSecretDestinations() (admission.Warnings, error) { + if trigger.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(trigger, nil, trigger.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (trigger *SqlDatabaseContainerTrigger) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerTrigger) @@ -333,6 +378,10 @@ type SqlDatabaseContainerTrigger_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerTriggerOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) PopulateFromARM(owner genruntim trigger.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_From_SqlDataba // Location trigger.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerTriggerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + trigger.OperatorSpec = &operatorSpec + } else { + trigger.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (trigger *SqlDatabaseContainerTrigger_Spec) AssignProperties_To_SqlDatabase // Location destination.Location = genruntime.ClonePointerToString(trigger.Location) + // OperatorSpec + if trigger.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerTriggerOperatorSpec + err := trigger.OperatorSpec.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if trigger.Options != nil { var option storage.CreateUpdateOptions @@ -876,6 +951,110 @@ func (trigger *SqlDatabaseContainerTrigger_STATUS) AssignProperties_To_SqlDataba return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerTriggerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec populates our SqlDatabaseContainerTriggerOperatorSpec from the provided source SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(source *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec populates the provided destination SqlDatabaseContainerTriggerOperatorSpec from our SqlDatabaseContainerTriggerOperatorSpec +func (operator *SqlDatabaseContainerTriggerOperatorSpec) AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(destination *storage.SqlDatabaseContainerTriggerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlTriggerGetProperties_Resource_STATUS struct { // Body: Body of the Trigger Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen_test.go index 39c7576e414..97bc1a7c7f4 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_trigger_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger(gens map[string] gens["Status"] = SqlDatabaseContainerTrigger_STATUSGenerator() } +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerTriggerOperatorSpec to SqlDatabaseContainerTriggerOperatorSpec via AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec & AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec tests if a specific instance of SqlDatabaseContainerTriggerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerTriggerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerTriggerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerTriggerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerTriggerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerTriggerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerTriggerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerTriggerOperatorSpecGenerator() +var sqlDatabaseContainerTriggerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerTriggerOperatorSpecGenerator returns a generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing. +func SqlDatabaseContainerTriggerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerTriggerOperatorSpecGenerator != nil { + return sqlDatabaseContainerTriggerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerTriggerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerTriggerOperatorSpec{}), generators) + + return sqlDatabaseContainerTriggerOperatorSpecGenerator +} + func Test_SqlDatabaseContainerTrigger_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,6 +503,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens ma // AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerTriggerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlTriggerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_container_types_gen.go index 9a4d5ce4a9a..8ae62a19b84 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (container *SqlDatabaseContainer) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainer resource func (container *SqlDatabaseContainer) defaultImpl() { container.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *SqlDatabaseContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *SqlDatabaseContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseContainer{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (container *SqlDatabaseContainer) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (container *SqlDatabaseContainer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference} + return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference, container.validateSecretDestinations, container.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (container *SqlDatabaseContainer) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return container.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (container *SqlDatabaseContainer) validateConfigMapDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(container, nil, container.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (container *SqlDatabaseContainer) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (container *SqlDatabaseContainer) validateSecretDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(container, nil, container.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (container *SqlDatabaseContainer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainer) @@ -333,6 +378,10 @@ type SqlDatabaseContainer_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (container *SqlDatabaseContainer_Spec) PopulateFromARM(owner genruntime.Arb container.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_From_SqlDatabaseCon // Location container.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (container *SqlDatabaseContainer_Spec) AssignProperties_To_SqlDatabaseConta // Location destination.Location = genruntime.ClonePointerToString(container.Location) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if container.Options != nil { var option storage.CreateUpdateOptions @@ -1994,6 +2069,110 @@ func (resource *SqlContainerResource) Initialize_From_SqlContainerGetProperties_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerOperatorSpec populates our SqlDatabaseContainerOperatorSpec from the provided source SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_From_SqlDatabaseContainerOperatorSpec(source *storage.SqlDatabaseContainerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerOperatorSpec populates the provided destination SqlDatabaseContainerOperatorSpec from our SqlDatabaseContainerOperatorSpec +func (operator *SqlDatabaseContainerOperatorSpec) AssignProperties_To_SqlDatabaseContainerOperatorSpec(destination *storage.SqlDatabaseContainerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB client encryption policy. type ClientEncryptionPolicy struct { // +kubebuilder:validation:Required diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_container_types_gen_test.go index d63ea6a2fd3..dde6bec3b15 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_types_gen_test.go @@ -2814,6 +2814,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainer(gens map[string]gopter. gens["Status"] = SqlDatabaseContainer_STATUSGenerator() } +func Test_SqlDatabaseContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerOperatorSpec to SqlDatabaseContainerOperatorSpec via AssignProperties_To_SqlDatabaseContainerOperatorSpec & AssignProperties_From_SqlDatabaseContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec tests if a specific instance of SqlDatabaseContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerOperatorSpecGenerator() +var sqlDatabaseContainerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerOperatorSpecGenerator returns a generator of SqlDatabaseContainerOperatorSpec instances for property testing. +func SqlDatabaseContainerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerOperatorSpecGenerator != nil { + return sqlDatabaseContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerOperatorSpec{}), generators) + + return sqlDatabaseContainerOperatorSpecGenerator +} + func Test_SqlDatabaseContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3056,6 +3153,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[strin // AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlContainerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen.go index 0f86f649f1c..8199fccdf0c 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (function *SqlDatabaseContainerUserDefinedFunction) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabaseContainerUserDefinedFunction resource func (function *SqlDatabaseContainerUserDefinedFunction) defaultImpl() { function.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) SecretDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseContainerUserDefinedFunction{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (function *SqlDatabaseContainerUserDefinedFunction) ValidateUpdate(old runt // createValidations validates the creation of the resource func (function *SqlDatabaseContainerUserDefinedFunction) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){function.validateResourceReferences, function.validateOwnerReference} + return []func() (admission.Warnings, error){function.validateResourceReferences, function.validateOwnerReference, function.validateSecretDestinations, function.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (function *SqlDatabaseContainerUserDefinedFunction) updateValidations() []f func(old runtime.Object) (admission.Warnings, error) { return function.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return function.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return function.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (function *SqlDatabaseContainerUserDefinedFunction) validateConfigMapDestinations() (admission.Warnings, error) { + if function.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(function, nil, function.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (function *SqlDatabaseContainerUserDefinedFunction) validateResourceReferen return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (function *SqlDatabaseContainerUserDefinedFunction) validateSecretDestinations() (admission.Warnings, error) { + if function.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(function, nil, function.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (function *SqlDatabaseContainerUserDefinedFunction) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseContainerUserDefinedFunction) @@ -333,6 +378,10 @@ type SqlDatabaseContainerUserDefinedFunction_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseContainerUserDefinedFunctionOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) PopulateFromARM(ow function.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_F // Location function.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + function.OperatorSpec = &operatorSpec + } else { + function.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (function *SqlDatabaseContainerUserDefinedFunction_Spec) AssignProperties_T // Location destination.Location = genruntime.ClonePointerToString(function.Location) + // OperatorSpec + if function.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := function.OperatorSpec.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if function.Options != nil { var option storage.CreateUpdateOptions @@ -876,6 +951,110 @@ func (function *SqlDatabaseContainerUserDefinedFunction_STATUS) AssignProperties return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerUserDefinedFunctionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates our SqlDatabaseContainerUserDefinedFunctionOperatorSpec from the provided source SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(source *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec populates the provided destination SqlDatabaseContainerUserDefinedFunctionOperatorSpec from our SqlDatabaseContainerUserDefinedFunctionOperatorSpec +func (operator *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(destination *storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type SqlUserDefinedFunctionGetProperties_Resource_STATUS struct { // Body: Body of the User Defined Function Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen_test.go index f5fcf19d847..dfad9aba538 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_container_user_defined_function_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction(gens gens["Status"] = SqlDatabaseContainerUserDefinedFunction_STATUSGenerator() } +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseContainerUserDefinedFunctionOperatorSpec to SqlDatabaseContainerUserDefinedFunctionOperatorSpec via AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec & AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec tests if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseContainerUserDefinedFunctionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerUserDefinedFunctionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() +var sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator returns a generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing. +func SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator != nil { + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpec{}), generators) + + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator +} + func Test_SqlDatabaseContainerUserDefinedFunction_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -406,6 +503,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_ // AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlUserDefinedFunctionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen.go index 2e3bad6e949..48494da0bc6 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *SqlDatabaseThroughputSetting) Default() { // defaultImpl applies the code generated defaults to the SqlDatabaseThroughputSetting resource func (setting *SqlDatabaseThroughputSetting) defaultImpl() {} +var _ configmaps.Exporter = &SqlDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabaseThroughputSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *SqlDatabaseThroughputSetting) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (setting *SqlDatabaseThroughputSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *SqlDatabaseThroughputSetting) updateValidations() []func(old runt func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *SqlDatabaseThroughputSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *SqlDatabaseThroughputSetting) validateResourceReferences() (admis return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *SqlDatabaseThroughputSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *SqlDatabaseThroughputSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabaseThroughputSetting) @@ -321,6 +366,10 @@ type SqlDatabaseThroughputSetting_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -392,6 +441,8 @@ func (setting *SqlDatabaseThroughputSetting_Spec) PopulateFromARM(owner genrunti setting.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -480,6 +531,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_From_SqlDatab // Location setting.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseThroughputSettingOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -515,6 +578,18 @@ func (setting *SqlDatabaseThroughputSetting_Spec) AssignProperties_To_SqlDatabas // Location destination.Location = genruntime.ClonePointerToString(setting.Location) + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseThroughputSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -800,6 +875,110 @@ func (setting *SqlDatabaseThroughputSetting_STATUS) AssignProperties_To_SqlDatab return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseThroughputSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec populates our SqlDatabaseThroughputSettingOperatorSpec from the provided source SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(source *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec populates the provided destination SqlDatabaseThroughputSettingOperatorSpec from our SqlDatabaseThroughputSettingOperatorSpec +func (operator *SqlDatabaseThroughputSettingOperatorSpec) AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(destination *storage.SqlDatabaseThroughputSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlDatabaseThroughputSetting{}, &SqlDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen_test.go index fa7d7629f8c..c426c2b8cd0 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_throughput_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting(gens map[string gens["Status"] = SqlDatabaseThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseThroughputSettingOperatorSpec to SqlDatabaseThroughputSettingOperatorSpec via AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec & AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec tests if a specific instance of SqlDatabaseThroughputSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseThroughputSettingOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseThroughputSettingOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseThroughputSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseThroughputSettingOperatorSpecGenerator() +var sqlDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseThroughputSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -405,5 +502,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens m // AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_database_types_gen.go b/v2/api/documentdb/v1api20231115/sql_database_types_gen.go index 03f6dcaac12..e9dc12ca1a1 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *SqlDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the SqlDatabase resource func (database *SqlDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &SqlDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *SqlDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *SqlDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *SqlDatabase) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (database *SqlDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *SqlDatabase) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *SqlDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *SqlDatabase) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *SqlDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *SqlDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlDatabase) @@ -333,6 +378,10 @@ type SqlDatabase_Spec struct { // Location: The location of the resource group to which the resource belongs. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // Options: A key-value pair of options to be applied for the request. This corresponds to the headers sent with the // request. Options *CreateUpdateOptions `json:"options,omitempty"` @@ -419,6 +468,8 @@ func (database *SqlDatabase_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne database.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Options": // copying flattened property: if typedInput.Properties != nil { @@ -524,6 +575,18 @@ func (database *SqlDatabase_Spec) AssignProperties_From_SqlDatabase_Spec(source // Location database.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_SqlDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Options if source.Options != nil { var option CreateUpdateOptions @@ -574,6 +637,18 @@ func (database *SqlDatabase_Spec) AssignProperties_To_SqlDatabase_Spec(destinati // Location destination.Location = genruntime.ClonePointerToString(database.Location) + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.SqlDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_SqlDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // Options if database.Options != nil { var option storage.CreateUpdateOptions @@ -1136,6 +1211,110 @@ func (resource *SqlDatabaseGetProperties_Resource_STATUS) AssignProperties_To_Sq return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlDatabaseOperatorSpec populates our SqlDatabaseOperatorSpec from the provided source SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_From_SqlDatabaseOperatorSpec(source *storage.SqlDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlDatabaseOperatorSpec populates the provided destination SqlDatabaseOperatorSpec from our SqlDatabaseOperatorSpec +func (operator *SqlDatabaseOperatorSpec) AssignProperties_To_SqlDatabaseOperatorSpec(destination *storage.SqlDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Cosmos DB SQL database resource object type SqlDatabaseResource struct { // CreateMode: Enum to indicate the mode of resource creation. diff --git a/v2/api/documentdb/v1api20231115/sql_database_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_database_types_gen_test.go index 17ddd4d3a05..64a7a26d400 100644 --- a/v2/api/documentdb/v1api20231115/sql_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_database_types_gen_test.go @@ -287,6 +287,103 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseGetProperties_Resource_STATUS(gen gens["RestoreParameters"] = gen.PtrOf(RestoreParametersBase_STATUSGenerator()) } +func Test_SqlDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlDatabaseOperatorSpec to SqlDatabaseOperatorSpec via AssignProperties_To_SqlDatabaseOperatorSpec & AssignProperties_From_SqlDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlDatabaseOperatorSpec tests if a specific instance of SqlDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlDatabaseOperatorSpec + err := copied.AssignProperties_To_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlDatabaseOperatorSpec + err = actual.AssignProperties_From_SqlDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseOperatorSpec runs a test to see if a specific instance of SqlDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseOperatorSpecGenerator() +var sqlDatabaseOperatorSpecGenerator gopter.Gen + +// SqlDatabaseOperatorSpecGenerator returns a generator of SqlDatabaseOperatorSpec instances for property testing. +func SqlDatabaseOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseOperatorSpecGenerator != nil { + return sqlDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseOperatorSpec{}), generators) + + return sqlDatabaseOperatorSpecGenerator +} + func Test_SqlDatabaseResource_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -645,6 +742,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForSqlDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen.go b/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen.go index e2be593b2dc..815df30babc 100644 --- a/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen.go +++ b/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (assignment *SqlRoleAssignment) Default() { // defaultImpl applies the code generated defaults to the SqlRoleAssignment resource func (assignment *SqlRoleAssignment) defaultImpl() {} +var _ configmaps.Exporter = &SqlRoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *SqlRoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlRoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *SqlRoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SqlRoleAssignment{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +225,7 @@ func (assignment *SqlRoleAssignment) ValidateUpdate(old runtime.Object) (admissi // createValidations validates the creation of the resource func (assignment *SqlRoleAssignment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOwnerReference, assignment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assignment.validateResourceReferences, assignment.validateOwnerReference, assignment.validateSecretDestinations, assignment.validateConfigMapDestinations, assignment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -221,12 +243,26 @@ func (assignment *SqlRoleAssignment) updateValidations() []func(old runtime.Obje func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assignment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assignment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assignment *SqlRoleAssignment) validateConfigMapDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assignment *SqlRoleAssignment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assignment.Spec) @@ -250,6 +286,14 @@ func (assignment *SqlRoleAssignment) validateResourceReferences() (admission.War return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assignment *SqlRoleAssignment) validateSecretDestinations() (admission.Warnings, error) { + if assignment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assignment, nil, assignment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assignment *SqlRoleAssignment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*SqlRoleAssignment) @@ -336,6 +380,10 @@ type SqlRoleAssignment_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SqlRoleAssignmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -415,6 +463,8 @@ func (assignment *SqlRoleAssignment_Spec) PopulateFromARM(owner genruntime.Arbit // Set property "AzureName": assignment.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": assignment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -510,6 +560,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_From_SqlRoleAssignmen // AzureName assignment.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SqlRoleAssignmentOperatorSpec + err := operatorSpec.AssignProperties_From_SqlRoleAssignmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + assignment.OperatorSpec = &operatorSpec + } else { + assignment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -547,6 +609,18 @@ func (assignment *SqlRoleAssignment_Spec) AssignProperties_To_SqlRoleAssignment_ // AzureName destination.AzureName = assignment.AzureName + // OperatorSpec + if assignment.OperatorSpec != nil { + var operatorSpec storage.SqlRoleAssignmentOperatorSpec + err := assignment.OperatorSpec.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SqlRoleAssignmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = assignment.OriginalVersion() @@ -816,6 +890,110 @@ func (assignment *SqlRoleAssignment_STATUS) AssignProperties_To_SqlRoleAssignmen return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlRoleAssignmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SqlRoleAssignmentOperatorSpec populates our SqlRoleAssignmentOperatorSpec from the provided source SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_From_SqlRoleAssignmentOperatorSpec(source *storage.SqlRoleAssignmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SqlRoleAssignmentOperatorSpec populates the provided destination SqlRoleAssignmentOperatorSpec from our SqlRoleAssignmentOperatorSpec +func (operator *SqlRoleAssignmentOperatorSpec) AssignProperties_To_SqlRoleAssignmentOperatorSpec(destination *storage.SqlRoleAssignmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&SqlRoleAssignment{}, &SqlRoleAssignmentList{}) } diff --git a/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen_test.go b/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen_test.go index 9be3685c339..61dd91095fc 100644 --- a/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/sql_role_assignment_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForSqlRoleAssignment(gens map[string]gopter.Gen gens["Status"] = SqlRoleAssignment_STATUSGenerator() } +func Test_SqlRoleAssignmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SqlRoleAssignmentOperatorSpec to SqlRoleAssignmentOperatorSpec via AssignProperties_To_SqlRoleAssignmentOperatorSpec & AssignProperties_From_SqlRoleAssignmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec tests if a specific instance of SqlRoleAssignmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SqlRoleAssignmentOperatorSpec + err := copied.AssignProperties_To_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SqlRoleAssignmentOperatorSpec + err = actual.AssignProperties_From_SqlRoleAssignmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SqlRoleAssignmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlRoleAssignmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec runs a test to see if a specific instance of SqlRoleAssignmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlRoleAssignmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlRoleAssignmentOperatorSpec instances for property testing - lazily instantiated by +// SqlRoleAssignmentOperatorSpecGenerator() +var sqlRoleAssignmentOperatorSpecGenerator gopter.Gen + +// SqlRoleAssignmentOperatorSpecGenerator returns a generator of SqlRoleAssignmentOperatorSpec instances for property testing. +func SqlRoleAssignmentOperatorSpecGenerator() gopter.Gen { + if sqlRoleAssignmentOperatorSpecGenerator != nil { + return sqlRoleAssignmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlRoleAssignmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignmentOperatorSpec{}), generators) + + return sqlRoleAssignmentOperatorSpecGenerator +} + func Test_SqlRoleAssignment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForSqlRoleAssignment_Spec(subject SqlRoleAssignment var sqlRoleAssignment_SpecGenerator gopter.Gen // SqlRoleAssignment_SpecGenerator returns a generator of SqlRoleAssignment_Spec instances for property testing. +// We first initialize sqlRoleAssignment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func SqlRoleAssignment_SpecGenerator() gopter.Gen { if sqlRoleAssignment_SpecGenerator != nil { return sqlRoleAssignment_SpecGenerator @@ -367,6 +467,12 @@ func SqlRoleAssignment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + return sqlRoleAssignment_SpecGenerator } @@ -377,3 +483,8 @@ func AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]g gens["RoleDefinitionId"] = gen.PtrOf(gen.AlphaString()) gens["Scope"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlRoleAssignmentOperatorSpecGenerator()) +} diff --git a/v2/api/documentdb/v1api20231115/storage/database_account_types_gen.go b/v2/api/documentdb/v1api20231115/storage/database_account_types_gen.go index 00f88613a9a..12a9683c3a4 100644 --- a/v2/api/documentdb/v1api20231115/storage/database_account_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/database_account_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (account *DatabaseAccount) SetConditions(conditions conditions.Conditions) account.Status.Conditions = conditions } +var _ configmaps.Exporter = &DatabaseAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *DatabaseAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DatabaseAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *DatabaseAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DatabaseAccount{} // AzureName returns the Azure name of the resource @@ -410,8 +433,10 @@ type DatabaseAccountKeysMetadata_STATUS struct { // Storage version of v1api20231115.DatabaseAccountOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type DatabaseAccountOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *DatabaseAccountOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20231115.FailoverPolicy_STATUS diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen.go index ae8adb915eb..69ee9dbf08a 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *MongodbDatabaseCollectionThroughputSetting) SetConditions(conditi setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollectionThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseCollectionThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollectionThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type MongodbDatabaseCollectionThroughputSettingList struct { // Storage version of v1api20231115.MongodbDatabaseCollectionThroughputSetting_Spec type MongodbDatabaseCollectionThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseCollectionThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (setting *MongodbDatabaseCollectionThroughputSetting_STATUS) ConvertStatusT return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20231115.MongodbDatabaseCollectionThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.ThroughputSettingsGetProperties_Resource_STATUS type ThroughputSettingsGetProperties_Resource_STATUS struct { AutoscaleSettings *AutoscaleSettingsResource_STATUS `json:"autoscaleSettings,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen_test.go index c55acfed662..152d6b10afc 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_throughput_setting_types_gen_test.go @@ -352,6 +352,61 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting(g gens["Status"] = MongodbDatabaseCollectionThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseCollectionThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec, MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionThroughputSettingOperatorSpec(subject MongodbDatabaseCollectionThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing - lazily +// instantiated by MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseCollectionThroughputSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -509,6 +564,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetti // AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollectionThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen.go index 0d8dd9db870..55d1b948345 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (collection *MongodbDatabaseCollection) SetConditions(conditions conditions collection.Status.Conditions = conditions } +var _ configmaps.Exporter = &MongodbDatabaseCollection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (collection *MongodbDatabaseCollection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseCollection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (collection *MongodbDatabaseCollection) SecretDestinationExpressions() []*core.DestinationExpression { + if collection.Spec.OperatorSpec == nil { + return nil + } + return collection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseCollection{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type MongodbDatabaseCollectionList struct { type MongodbDatabaseCollection_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseCollectionOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -236,6 +260,14 @@ type MongoDBCollectionResource struct { ShardKey map[string]string `json:"shardKey,omitempty"` } +// Storage version of v1api20231115.MongodbDatabaseCollectionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseCollectionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.MongoIndex // Cosmos DB MongoDB collection index key type MongoIndex struct { diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen_test.go index 460641a8449..38444051dde 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_collection_types_gen_test.go @@ -610,6 +610,61 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection(gens map[string]go gens["Status"] = MongodbDatabaseCollection_STATUSGenerator() } +func Test_MongodbDatabaseCollectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseCollectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec, MongodbDatabaseCollectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec runs a test to see if a specific instance of MongodbDatabaseCollectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseCollectionOperatorSpec(subject MongodbDatabaseCollectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseCollectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseCollectionOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseCollectionOperatorSpecGenerator() +var mongodbDatabaseCollectionOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseCollectionOperatorSpecGenerator returns a generator of MongodbDatabaseCollectionOperatorSpec instances for property testing. +func MongodbDatabaseCollectionOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseCollectionOperatorSpecGenerator != nil { + return mongodbDatabaseCollectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseCollectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseCollectionOperatorSpec{}), generators) + + return mongodbDatabaseCollectionOperatorSpecGenerator +} + func Test_MongodbDatabaseCollection_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -769,6 +824,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[ // AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseCollection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseCollectionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBCollectionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen.go index c144c479b2e..435f75d4ef3 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *MongodbDatabaseThroughputSetting) SetConditions(conditions condit setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &MongodbDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *MongodbDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *MongodbDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type MongodbDatabaseThroughputSettingList struct { // Storage version of v1api20231115.MongodbDatabaseThroughputSetting_Spec type MongodbDatabaseThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (setting *MongodbDatabaseThroughputSetting_STATUS) ConvertStatusTo(destinat return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20231115.MongodbDatabaseThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&MongodbDatabaseThroughputSetting{}, &MongodbDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen_test.go index 3e487d9f76c..c93e9e5a3c6 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_throughput_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting(gens map[st gens["Status"] = MongodbDatabaseThroughputSetting_STATUSGenerator() } +func Test_MongodbDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec, MongodbDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of MongodbDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseThroughputSettingOperatorSpec(subject MongodbDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseThroughputSettingOperatorSpecGenerator() +var mongodbDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseThroughputSettingOperatorSpecGenerator returns a generator of MongodbDatabaseThroughputSettingOperatorSpec instances for property testing. +func MongodbDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseThroughputSettingOperatorSpecGenerator != nil { + return mongodbDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseThroughputSettingOperatorSpec{}), generators) + + return mongodbDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_MongodbDatabaseThroughputSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -236,5 +291,6 @@ func AddIndependentPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(ge // AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen.go index 3e7a8c8baaa..362f6502bb7 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *MongodbDatabase) SetConditions(conditions conditions.Conditions) database.Status.Conditions = conditions } +var _ configmaps.Exporter = &MongodbDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *MongodbDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MongodbDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *MongodbDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MongodbDatabase{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type MongodbDatabaseList struct { type MongodbDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MongodbDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -230,6 +254,14 @@ type MongoDBDatabaseGetProperties_Resource_STATUS struct { Ts *float64 `json:"_ts,omitempty"` } +// Storage version of v1api20231115.MongodbDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MongodbDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.MongoDBDatabaseResource // Cosmos DB MongoDB database resource object type MongoDBDatabaseResource struct { diff --git a/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen_test.go index 716eeab9e81..56a474f6740 100644 --- a/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/mongodb_database_types_gen_test.go @@ -429,6 +429,61 @@ func AddRelatedPropertyGeneratorsForMongodbDatabase(gens map[string]gopter.Gen) gens["Status"] = MongodbDatabase_STATUSGenerator() } +func Test_MongodbDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MongodbDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMongodbDatabaseOperatorSpec, MongodbDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMongodbDatabaseOperatorSpec runs a test to see if a specific instance of MongodbDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMongodbDatabaseOperatorSpec(subject MongodbDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MongodbDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MongodbDatabaseOperatorSpec instances for property testing - lazily instantiated by +// MongodbDatabaseOperatorSpecGenerator() +var mongodbDatabaseOperatorSpecGenerator gopter.Gen + +// MongodbDatabaseOperatorSpecGenerator returns a generator of MongodbDatabaseOperatorSpec instances for property testing. +func MongodbDatabaseOperatorSpecGenerator() gopter.Gen { + if mongodbDatabaseOperatorSpecGenerator != nil { + return mongodbDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + mongodbDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MongodbDatabaseOperatorSpec{}), generators) + + return mongodbDatabaseOperatorSpecGenerator +} + func Test_MongodbDatabase_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -588,6 +643,7 @@ func AddIndependentPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForMongodbDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForMongodbDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(MongodbDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(MongoDBDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen.go index bd6caa89562..7ee5de80849 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (procedure *SqlDatabaseContainerStoredProcedure) SetConditions(conditions c procedure.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerStoredProcedure{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (procedure *SqlDatabaseContainerStoredProcedure) SecretDestinationExpressions() []*core.DestinationExpression { + if procedure.Spec.OperatorSpec == nil { + return nil + } + return procedure.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerStoredProcedure{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type SqlDatabaseContainerStoredProcedureList struct { type SqlDatabaseContainerStoredProcedure_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerStoredProcedureOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (procedure *SqlDatabaseContainerStoredProcedure_STATUS) ConvertStatusTo(des return destination.ConvertStatusFrom(procedure) } +// Storage version of v1api20231115.SqlDatabaseContainerStoredProcedureOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerStoredProcedureOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.SqlStoredProcedureGetProperties_Resource_STATUS type SqlStoredProcedureGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen_test.go index d1a7e20e462..8bef85a6fd9 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_stored_procedure_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure(gens map gens["Status"] = SqlDatabaseContainerStoredProcedure_STATUSGenerator() } +func Test_SqlDatabaseContainerStoredProcedureOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerStoredProcedureOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec, SqlDatabaseContainerStoredProcedureOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerStoredProcedureOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerStoredProcedureOperatorSpec(subject SqlDatabaseContainerStoredProcedureOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerStoredProcedureOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() +var sqlDatabaseContainerStoredProcedureOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerStoredProcedureOperatorSpecGenerator returns a generator of SqlDatabaseContainerStoredProcedureOperatorSpec instances for property testing. +func SqlDatabaseContainerStoredProcedureOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerStoredProcedureOperatorSpecGenerator != nil { + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerStoredProcedureOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerStoredProcedureOperatorSpec{}), generators) + + return sqlDatabaseContainerStoredProcedureOperatorSpecGenerator +} + func Test_SqlDatabaseContainerStoredProcedure_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -237,6 +292,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec // AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerStoredProcedure_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerStoredProcedureOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlStoredProcedureResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen.go index 567fcc6f165..a205f14d7fc 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *SqlDatabaseContainerThroughputSetting) SetConditions(conditions c setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseContainerThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type SqlDatabaseContainerThroughputSettingList struct { // Storage version of v1api20231115.SqlDatabaseContainerThroughputSetting_Spec type SqlDatabaseContainerThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (setting *SqlDatabaseContainerThroughputSetting_STATUS) ConvertStatusTo(des return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20231115.SqlDatabaseContainerThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&SqlDatabaseContainerThroughputSetting{}, &SqlDatabaseContainerThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen_test.go index 85fa075194e..bd94c1cc78a 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_throughput_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting(gens m gens["Status"] = SqlDatabaseContainerThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseContainerThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec, SqlDatabaseContainerThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerThroughputSettingOperatorSpec(subject SqlDatabaseContainerThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() +var sqlDatabaseContainerThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseContainerThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseContainerThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseContainerThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseContainerThroughputSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -236,5 +291,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Sp // AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen.go index 02b41c7b2aa..4c9e18d242f 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (trigger *SqlDatabaseContainerTrigger) SetConditions(conditions conditions. trigger.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseContainerTrigger{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (trigger *SqlDatabaseContainerTrigger) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerTrigger{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (trigger *SqlDatabaseContainerTrigger) SecretDestinationExpressions() []*core.DestinationExpression { + if trigger.Spec.OperatorSpec == nil { + return nil + } + return trigger.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerTrigger{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type SqlDatabaseContainerTriggerList struct { type SqlDatabaseContainerTrigger_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerTriggerOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (trigger *SqlDatabaseContainerTrigger_STATUS) ConvertStatusTo(destination g return destination.ConvertStatusFrom(trigger) } +// Storage version of v1api20231115.SqlDatabaseContainerTriggerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerTriggerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.SqlTriggerGetProperties_Resource_STATUS type SqlTriggerGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen_test.go index 7efe3f43a6a..2b54023a013 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_trigger_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger(gens map[string] gens["Status"] = SqlDatabaseContainerTrigger_STATUSGenerator() } +func Test_SqlDatabaseContainerTriggerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerTriggerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec, SqlDatabaseContainerTriggerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerTriggerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerTriggerOperatorSpec(subject SqlDatabaseContainerTriggerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerTriggerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerTriggerOperatorSpecGenerator() +var sqlDatabaseContainerTriggerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerTriggerOperatorSpecGenerator returns a generator of SqlDatabaseContainerTriggerOperatorSpec instances for property testing. +func SqlDatabaseContainerTriggerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerTriggerOperatorSpecGenerator != nil { + return sqlDatabaseContainerTriggerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerTriggerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerTriggerOperatorSpec{}), generators) + + return sqlDatabaseContainerTriggerOperatorSpecGenerator +} + func Test_SqlDatabaseContainerTrigger_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -237,6 +292,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens ma // AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerTrigger_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerTriggerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlTriggerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen.go index a19b7f54122..59f2323fa57 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (container *SqlDatabaseContainer) SetConditions(conditions conditions.Condi container.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *SqlDatabaseContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *SqlDatabaseContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainer{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type SqlDatabaseContainerList struct { type SqlDatabaseContainer_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -246,6 +270,14 @@ type SqlContainerResource struct { UniqueKeyPolicy *UniqueKeyPolicy `json:"uniqueKeyPolicy,omitempty"` } +// Storage version of v1api20231115.SqlDatabaseContainerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.ClientEncryptionPolicy // Cosmos DB client encryption policy. type ClientEncryptionPolicy struct { diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen_test.go index d3931b7d90f..ff649ac98d6 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_types_gen_test.go @@ -1700,6 +1700,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainer(gens map[string]gopter. gens["Status"] = SqlDatabaseContainer_STATUSGenerator() } +func Test_SqlDatabaseContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec, SqlDatabaseContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerOperatorSpec(subject SqlDatabaseContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseContainerOperatorSpecGenerator() +var sqlDatabaseContainerOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerOperatorSpecGenerator returns a generator of SqlDatabaseContainerOperatorSpec instances for property testing. +func SqlDatabaseContainerOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerOperatorSpecGenerator != nil { + return sqlDatabaseContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerOperatorSpec{}), generators) + + return sqlDatabaseContainerOperatorSpecGenerator +} + func Test_SqlDatabaseContainer_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1859,6 +1914,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[strin // AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainer_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlContainerResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen.go index 8b9f1fbdc1e..8c7fe33076b 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (function *SqlDatabaseContainerUserDefinedFunction) SetConditions(condition function.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseContainerUserDefinedFunction{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (function *SqlDatabaseContainerUserDefinedFunction) SecretDestinationExpressions() []*core.DestinationExpression { + if function.Spec.OperatorSpec == nil { + return nil + } + return function.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseContainerUserDefinedFunction{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type SqlDatabaseContainerUserDefinedFunctionList struct { type SqlDatabaseContainerUserDefinedFunction_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseContainerUserDefinedFunctionOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (function *SqlDatabaseContainerUserDefinedFunction_STATUS) ConvertStatusTo( return destination.ConvertStatusFrom(function) } +// Storage version of v1api20231115.SqlDatabaseContainerUserDefinedFunctionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseContainerUserDefinedFunctionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.SqlUserDefinedFunctionGetProperties_Resource_STATUS type SqlUserDefinedFunctionGetProperties_Resource_STATUS struct { Body *string `json:"body,omitempty"` diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen_test.go index 20c90039108..b35ac5e0901 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_container_user_defined_function_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction(gens gens["Status"] = SqlDatabaseContainerUserDefinedFunction_STATUSGenerator() } +func Test_SqlDatabaseContainerUserDefinedFunctionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseContainerUserDefinedFunctionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec, SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec runs a test to see if a specific instance of SqlDatabaseContainerUserDefinedFunctionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseContainerUserDefinedFunctionOperatorSpec(subject SqlDatabaseContainerUserDefinedFunctionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseContainerUserDefinedFunctionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing - lazily instantiated +// by SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() +var sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator gopter.Gen + +// SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator returns a generator of SqlDatabaseContainerUserDefinedFunctionOperatorSpec instances for property testing. +func SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator != nil { + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpec{}), generators) + + return sqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator +} + func Test_SqlDatabaseContainerUserDefinedFunction_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -237,6 +292,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_ // AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseContainerUserDefinedFunction_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseContainerUserDefinedFunctionOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlUserDefinedFunctionResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen.go index a42c153e14b..30fe45148f5 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *SqlDatabaseThroughputSetting) SetConditions(conditions conditions setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabaseThroughputSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *SqlDatabaseThroughputSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabaseThroughputSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *SqlDatabaseThroughputSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabaseThroughputSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type SqlDatabaseThroughputSettingList struct { // Storage version of v1api20231115.SqlDatabaseThroughputSetting_Spec type SqlDatabaseThroughputSetting_Spec struct { - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseThroughputSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (setting *SqlDatabaseThroughputSetting_STATUS) ConvertStatusTo(destination return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20231115.SqlDatabaseThroughputSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseThroughputSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&SqlDatabaseThroughputSetting{}, &SqlDatabaseThroughputSettingList{}) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen_test.go index a5c89270a58..f2154f8fe50 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_throughput_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting(gens map[string gens["Status"] = SqlDatabaseThroughputSetting_STATUSGenerator() } +func Test_SqlDatabaseThroughputSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseThroughputSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec, SqlDatabaseThroughputSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec runs a test to see if a specific instance of SqlDatabaseThroughputSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseThroughputSettingOperatorSpec(subject SqlDatabaseThroughputSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseThroughputSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseThroughputSettingOperatorSpecGenerator() +var sqlDatabaseThroughputSettingOperatorSpecGenerator gopter.Gen + +// SqlDatabaseThroughputSettingOperatorSpecGenerator returns a generator of SqlDatabaseThroughputSettingOperatorSpec instances for property testing. +func SqlDatabaseThroughputSettingOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseThroughputSettingOperatorSpecGenerator != nil { + return sqlDatabaseThroughputSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseThroughputSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseThroughputSettingOperatorSpec{}), generators) + + return sqlDatabaseThroughputSettingOperatorSpecGenerator +} + func Test_SqlDatabaseThroughputSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -236,5 +291,6 @@ func AddIndependentPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens m // AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabaseThroughputSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseThroughputSettingOperatorSpecGenerator()) gens["Resource"] = gen.PtrOf(ThroughputSettingsResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen.go index 4ba421573c1..e110784575c 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *SqlDatabase) SetConditions(conditions conditions.Conditions) { database.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *SqlDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *SqlDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlDatabase{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type SqlDatabaseList struct { type SqlDatabase_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - Options *CreateUpdateOptions `json:"options,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *SqlDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + Options *CreateUpdateOptions `json:"options,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -223,6 +247,14 @@ type SqlDatabaseGetProperties_Resource_STATUS struct { Users *string `json:"_users,omitempty"` } +// Storage version of v1api20231115.SqlDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231115.SqlDatabaseResource // Cosmos DB SQL database resource object type SqlDatabaseResource struct { diff --git a/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen_test.go index 6f52ccc8a8a..517875e2266 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_database_types_gen_test.go @@ -159,6 +159,61 @@ func AddRelatedPropertyGeneratorsForSqlDatabaseGetProperties_Resource_STATUS(gen gens["RestoreParameters"] = gen.PtrOf(RestoreParametersBase_STATUSGenerator()) } +func Test_SqlDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlDatabaseOperatorSpec, SqlDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlDatabaseOperatorSpec runs a test to see if a specific instance of SqlDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlDatabaseOperatorSpec(subject SqlDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlDatabaseOperatorSpec instances for property testing - lazily instantiated by +// SqlDatabaseOperatorSpecGenerator() +var sqlDatabaseOperatorSpecGenerator gopter.Gen + +// SqlDatabaseOperatorSpecGenerator returns a generator of SqlDatabaseOperatorSpec instances for property testing. +func SqlDatabaseOperatorSpecGenerator() gopter.Gen { + if sqlDatabaseOperatorSpecGenerator != nil { + return sqlDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlDatabaseOperatorSpec{}), generators) + + return sqlDatabaseOperatorSpecGenerator +} + func Test_SqlDatabaseResource_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -392,6 +447,7 @@ func AddIndependentPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForSqlDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForSqlDatabase_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlDatabaseOperatorSpecGenerator()) gens["Options"] = gen.PtrOf(CreateUpdateOptionsGenerator()) gens["Resource"] = gen.PtrOf(SqlDatabaseResourceGenerator()) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen.go b/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen.go index 160a6bcdeb5..8a744bdd950 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (assignment *SqlRoleAssignment) SetConditions(conditions conditions.Conditi assignment.Status.Conditions = conditions } +var _ configmaps.Exporter = &SqlRoleAssignment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assignment *SqlRoleAssignment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SqlRoleAssignment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assignment *SqlRoleAssignment) SecretDestinationExpressions() []*core.DestinationExpression { + if assignment.Spec.OperatorSpec == nil { + return nil + } + return assignment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SqlRoleAssignment{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type SqlRoleAssignmentList struct { type SqlRoleAssignment_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *SqlRoleAssignmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (assignment *SqlRoleAssignment_STATUS) ConvertStatusTo(destination genrunti return destination.ConvertStatusFrom(assignment) } +// Storage version of v1api20231115.SqlRoleAssignmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SqlRoleAssignmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&SqlRoleAssignment{}, &SqlRoleAssignmentList{}) } diff --git a/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen_test.go b/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen_test.go index b1aa36eab27..678658749e5 100644 --- a/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen_test.go +++ b/v2/api/documentdb/v1api20231115/storage/sql_role_assignment_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForSqlRoleAssignment(gens map[string]gopter.Gen gens["Status"] = SqlRoleAssignment_STATUSGenerator() } +func Test_SqlRoleAssignmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SqlRoleAssignmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec, SqlRoleAssignmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec runs a test to see if a specific instance of SqlRoleAssignmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSqlRoleAssignmentOperatorSpec(subject SqlRoleAssignmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SqlRoleAssignmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SqlRoleAssignmentOperatorSpec instances for property testing - lazily instantiated by +// SqlRoleAssignmentOperatorSpecGenerator() +var sqlRoleAssignmentOperatorSpecGenerator gopter.Gen + +// SqlRoleAssignmentOperatorSpecGenerator returns a generator of SqlRoleAssignmentOperatorSpec instances for property testing. +func SqlRoleAssignmentOperatorSpecGenerator() gopter.Gen { + if sqlRoleAssignmentOperatorSpecGenerator != nil { + return sqlRoleAssignmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + sqlRoleAssignmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignmentOperatorSpec{}), generators) + + return sqlRoleAssignmentOperatorSpecGenerator +} + func Test_SqlRoleAssignment_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForSqlRoleAssignment_Spec(subject SqlRoleAssignment var sqlRoleAssignment_SpecGenerator gopter.Gen // SqlRoleAssignment_SpecGenerator returns a generator of SqlRoleAssignment_Spec instances for property testing. +// We first initialize sqlRoleAssignment_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func SqlRoleAssignment_SpecGenerator() gopter.Gen { if sqlRoleAssignment_SpecGenerator != nil { return sqlRoleAssignment_SpecGenerator @@ -197,6 +255,12 @@ func SqlRoleAssignment_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(generators) + sqlRoleAssignment_SpecGenerator = gen.Struct(reflect.TypeOf(SqlRoleAssignment_Spec{}), generators) + return sqlRoleAssignment_SpecGenerator } @@ -208,3 +272,8 @@ func AddIndependentPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]g gens["RoleDefinitionId"] = gen.PtrOf(gen.AlphaString()) gens["Scope"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForSqlRoleAssignment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(SqlRoleAssignmentOperatorSpecGenerator()) +} diff --git a/v2/api/documentdb/v1api20231115/storage/structure.txt b/v2/api/documentdb/v1api20231115/storage/structure.txt index ad6c6c2bc0d..07f60d0f5af 100644 --- a/v2/api/documentdb/v1api20231115/storage/structure.txt +++ b/v2/api/documentdb/v1api20231115/storage/structure.txt @@ -92,8 +92,10 @@ DatabaseAccount: Resource │ ├── MinimalTlsVersion: *string │ ├── NetworkAclBypass: *string │ ├── NetworkAclBypassResourceReferences: genruntime.ResourceReference[] -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── DocumentEndpoint: *genruntime.SecretDestination │ │ ├── PrimaryMasterKey: *genruntime.SecretDestination @@ -292,9 +294,13 @@ DatabaseAccount: Resource └── ProvisioningState: *string MongodbDatabase: Resource ├── Owner: documentdb/v1api20231115.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -340,9 +346,13 @@ MongodbDatabase: Resource └── Type: *string MongodbDatabaseCollection: Resource ├── Owner: documentdb/v1api20231115.MongodbDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -410,8 +420,12 @@ MongodbDatabaseCollection: Resource └── Type: *string MongodbDatabaseCollectionThroughputSetting: Resource ├── Owner: documentdb/v1api20231115.MongodbDatabaseCollection -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -458,8 +472,12 @@ MongodbDatabaseCollectionThroughputSetting: Resource └── Type: *string MongodbDatabaseThroughputSetting: Resource ├── Owner: documentdb/v1api20231115.MongodbDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -506,9 +524,13 @@ MongodbDatabaseThroughputSetting: Resource └── Type: *string SqlDatabase: Resource ├── Owner: documentdb/v1api20231115.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -556,9 +578,13 @@ SqlDatabase: Resource └── Type: *string SqlDatabaseContainer: Resource ├── Owner: documentdb/v1api20231115.SqlDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -711,9 +737,13 @@ SqlDatabaseContainer: Resource └── Type: *string SqlDatabaseContainerStoredProcedure: Resource ├── Owner: documentdb/v1api20231115.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -745,8 +775,12 @@ SqlDatabaseContainerStoredProcedure: Resource └── Type: *string SqlDatabaseContainerThroughputSetting: Resource ├── Owner: documentdb/v1api20231115.SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -793,9 +827,13 @@ SqlDatabaseContainerThroughputSetting: Resource └── Type: *string SqlDatabaseContainerTrigger: Resource ├── Owner: documentdb/v1api20231115.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -831,9 +869,13 @@ SqlDatabaseContainerTrigger: Resource └── Type: *string SqlDatabaseContainerUserDefinedFunction: Resource ├── Owner: documentdb/v1api20231115.SqlDatabaseContainer -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (3 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) │ │ │ ├── MaxThroughput: *int @@ -865,8 +907,12 @@ SqlDatabaseContainerUserDefinedFunction: Resource └── Type: *string SqlDatabaseThroughputSetting: Resource ├── Owner: documentdb/v1api20231115.SqlDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -913,8 +959,12 @@ SqlDatabaseThroughputSetting: Resource └── Type: *string SqlRoleAssignment: Resource ├── Owner: documentdb/v1api20231115.DatabaseAccount -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrincipalId: *string diff --git a/v2/api/documentdb/v1api20231115/storage/zz_generated.deepcopy.go b/v2/api/documentdb/v1api20231115/storage/zz_generated.deepcopy.go index 4ebe17fc1a5..4c1531d46b6 100644 --- a/v2/api/documentdb/v1api20231115/storage/zz_generated.deepcopy.go +++ b/v2/api/documentdb/v1api20231115/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1485,6 +1486,17 @@ func (in *DatabaseAccountOperatorSecrets) DeepCopy() *DatabaseAccountOperatorSec // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -1492,6 +1504,17 @@ func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperator (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(DatabaseAccountOperatorSecrets) @@ -3242,6 +3265,50 @@ func (in *MongodbDatabaseCollectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionOperatorSpec. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopy() *MongodbDatabaseCollectionOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting) { *out = *in @@ -3301,6 +3368,50 @@ func (in *MongodbDatabaseCollectionThroughputSettingList) DeepCopyObject() runti return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionThroughputSettingOperatorSpec. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseCollectionThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting_STATUS) { *out = *in @@ -3370,6 +3481,11 @@ func (in *MongodbDatabaseCollectionThroughputSetting_Spec) DeepCopyInto(out *Mon *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3480,6 +3596,11 @@ func (in *MongodbDatabaseCollection_Spec) DeepCopyInto(out *MongodbDatabaseColle *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3553,6 +3674,50 @@ func (in *MongodbDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseOperatorSpec) DeepCopyInto(out *MongodbDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseOperatorSpec. +func (in *MongodbDatabaseOperatorSpec) DeepCopy() *MongodbDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting) DeepCopyInto(out *MongodbDatabaseThroughputSetting) { *out = *in @@ -3612,6 +3777,50 @@ func (in *MongodbDatabaseThroughputSettingList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseThroughputSettingOperatorSpec. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseThroughputSetting_STATUS) { *out = *in @@ -3681,6 +3890,11 @@ func (in *MongodbDatabaseThroughputSetting_Spec) DeepCopyInto(out *MongodbDataba *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3791,6 +4005,11 @@ func (in *MongodbDatabase_Spec) DeepCopyInto(out *MongodbDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4538,6 +4757,50 @@ func (in *SqlDatabaseContainerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerOperatorSpec. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopy() *SqlDatabaseContainerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure) { *out = *in @@ -4597,6 +4860,50 @@ func (in *SqlDatabaseContainerStoredProcedureList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerStoredProcedureOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerStoredProcedureOperatorSpec. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopy() *SqlDatabaseContainerStoredProcedureOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerStoredProcedureOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure_STATUS) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure_STATUS) { *out = *in @@ -4666,6 +4973,11 @@ func (in *SqlDatabaseContainerStoredProcedure_Spec) DeepCopyInto(out *SqlDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerStoredProcedureOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4766,6 +5078,50 @@ func (in *SqlDatabaseContainerThroughputSettingList) DeepCopyObject() runtime.Ob return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerThroughputSettingOperatorSpec. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseContainerThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseContainerThroughputSetting_STATUS) { *out = *in @@ -4835,6 +5191,11 @@ func (in *SqlDatabaseContainerThroughputSetting_Spec) DeepCopyInto(out *SqlDatab *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4930,6 +5291,50 @@ func (in *SqlDatabaseContainerTriggerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerTriggerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerTriggerOperatorSpec. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopy() *SqlDatabaseContainerTriggerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerTriggerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerTrigger_STATUS) DeepCopyInto(out *SqlDatabaseContainerTrigger_STATUS) { *out = *in @@ -4999,6 +5404,11 @@ func (in *SqlDatabaseContainerTrigger_Spec) DeepCopyInto(out *SqlDatabaseContain *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerTriggerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -5099,6 +5509,50 @@ func (in *SqlDatabaseContainerUserDefinedFunctionList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerUserDefinedFunctionOperatorSpec. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopy() *SqlDatabaseContainerUserDefinedFunctionOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerUserDefinedFunction_STATUS) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunction_STATUS) { *out = *in @@ -5168,6 +5622,11 @@ func (in *SqlDatabaseContainerUserDefinedFunction_Spec) DeepCopyInto(out *SqlDat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -5283,6 +5742,11 @@ func (in *SqlDatabaseContainer_Spec) DeepCopyInto(out *SqlDatabaseContainer_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -5418,6 +5882,50 @@ func (in *SqlDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseOperatorSpec) DeepCopyInto(out *SqlDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseOperatorSpec. +func (in *SqlDatabaseOperatorSpec) DeepCopy() *SqlDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseResource) DeepCopyInto(out *SqlDatabaseResource) { *out = *in @@ -5514,6 +6022,50 @@ func (in *SqlDatabaseThroughputSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseThroughputSettingOperatorSpec. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseThroughputSetting_STATUS) { *out = *in @@ -5583,6 +6135,11 @@ func (in *SqlDatabaseThroughputSetting_Spec) DeepCopyInto(out *SqlDatabaseThroug *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5693,6 +6250,11 @@ func (in *SqlDatabase_Spec) DeepCopyInto(out *SqlDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -5793,6 +6355,50 @@ func (in *SqlRoleAssignmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopyInto(out *SqlRoleAssignmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlRoleAssignmentOperatorSpec. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopy() *SqlRoleAssignmentOperatorSpec { + if in == nil { + return nil + } + out := new(SqlRoleAssignmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_STATUS) DeepCopyInto(out *SqlRoleAssignment_STATUS) { *out = *in @@ -5855,6 +6461,11 @@ func (in *SqlRoleAssignment_STATUS) DeepCopy() *SqlRoleAssignment_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_Spec) DeepCopyInto(out *SqlRoleAssignment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlRoleAssignmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/documentdb/v1api20231115/structure.txt b/v2/api/documentdb/v1api20231115/structure.txt index 187365ce95b..57205fe1d41 100644 --- a/v2/api/documentdb/v1api20231115/structure.txt +++ b/v2/api/documentdb/v1api20231115/structure.txt @@ -134,7 +134,9 @@ DatabaseAccount: Resource │ │ ├── "AzureServices" │ │ └── "None" │ ├── NetworkAclBypassResourceReferences: genruntime.ResourceReference[] -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── DocumentEndpoint: *genruntime.SecretDestination │ │ ├── PrimaryMasterKey: *genruntime.SecretDestination @@ -356,9 +358,12 @@ DatabaseAccount: Resource └── ProvisioningState: *string MongodbDatabase: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -397,9 +402,12 @@ MongodbDatabase: Resource └── Type: *string MongodbDatabaseCollection: Resource ├── Owner: MongodbDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -454,8 +462,11 @@ MongodbDatabaseCollection: Resource └── Type: *string MongodbDatabaseCollectionThroughputSetting: Resource ├── Owner: MongodbDatabaseCollection -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -491,8 +502,11 @@ MongodbDatabaseCollectionThroughputSetting: Resource └── Type: *string MongodbDatabaseThroughputSetting: Resource ├── Owner: MongodbDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -528,9 +542,12 @@ MongodbDatabaseThroughputSetting: Resource └── Type: *string SqlDatabase: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -571,9 +588,12 @@ SqlDatabase: Resource └── Type: *string SqlDatabaseContainer: Resource ├── Owner: SqlDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -743,9 +763,12 @@ SqlDatabaseContainer: Resource └── Type: *string SqlDatabaseContainerStoredProcedure: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -770,8 +793,11 @@ SqlDatabaseContainerStoredProcedure: Resource └── Type: *string SqlDatabaseContainerThroughputSetting: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -807,9 +833,12 @@ SqlDatabaseContainerThroughputSetting: Resource └── Type: *string SqlDatabaseContainerTrigger: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -852,9 +881,12 @@ SqlDatabaseContainerTrigger: Resource └── Type: *string SqlDatabaseContainerUserDefinedFunction: Resource ├── Owner: SqlDatabaseContainer -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Options: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (1 property) │ │ │ └── MaxThroughput: *int @@ -879,8 +911,11 @@ SqlDatabaseContainerUserDefinedFunction: Resource └── Type: *string SqlDatabaseThroughputSetting: Resource ├── Owner: SqlDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Resource: *Object (2 properties) │ │ ├── AutoscaleSettings: *Object (2 properties) @@ -916,8 +951,11 @@ SqlDatabaseThroughputSetting: Resource └── Type: *string SqlRoleAssignment: Resource ├── Owner: DatabaseAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrincipalId: *string │ ├── PrincipalIdFromConfig: *genruntime.ConfigMapReference diff --git a/v2/api/documentdb/v1api20231115/zz_generated.deepcopy.go b/v2/api/documentdb/v1api20231115/zz_generated.deepcopy.go index 12ea24ab3d9..2ddc46c396d 100644 --- a/v2/api/documentdb/v1api20231115/zz_generated.deepcopy.go +++ b/v2/api/documentdb/v1api20231115/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20231115 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1191,6 +1192,28 @@ func (in *DatabaseAccountOperatorSecrets) DeepCopy() *DatabaseAccountOperatorSec // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DatabaseAccountOperatorSpec) DeepCopyInto(out *DatabaseAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(DatabaseAccountOperatorSecrets) @@ -2715,6 +2738,43 @@ func (in *MongodbDatabaseCollectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionOperatorSpec. +func (in *MongodbDatabaseCollectionOperatorSpec) DeepCopy() *MongodbDatabaseCollectionOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting) { *out = *in @@ -2774,6 +2834,43 @@ func (in *MongodbDatabaseCollectionThroughputSettingList) DeepCopyObject() runti return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseCollectionThroughputSettingOperatorSpec. +func (in *MongodbDatabaseCollectionThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseCollectionThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseCollectionThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseCollectionThroughputSetting_STATUS) { *out = *in @@ -2836,6 +2933,11 @@ func (in *MongodbDatabaseCollectionThroughputSetting_Spec) DeepCopyInto(out *Mon *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2932,6 +3034,11 @@ func (in *MongodbDatabaseCollection_Spec) DeepCopyInto(out *MongodbDatabaseColle *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseCollectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -2998,6 +3105,43 @@ func (in *MongodbDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseOperatorSpec) DeepCopyInto(out *MongodbDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseOperatorSpec. +func (in *MongodbDatabaseOperatorSpec) DeepCopy() *MongodbDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting) DeepCopyInto(out *MongodbDatabaseThroughputSetting) { *out = *in @@ -3057,6 +3201,43 @@ func (in *MongodbDatabaseThroughputSettingList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *MongodbDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongodbDatabaseThroughputSettingOperatorSpec. +func (in *MongodbDatabaseThroughputSettingOperatorSpec) DeepCopy() *MongodbDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(MongodbDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MongodbDatabaseThroughputSetting_STATUS) DeepCopyInto(out *MongodbDatabaseThroughputSetting_STATUS) { *out = *in @@ -3119,6 +3300,11 @@ func (in *MongodbDatabaseThroughputSetting_Spec) DeepCopyInto(out *MongodbDataba *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3215,6 +3401,11 @@ func (in *MongodbDatabase_Spec) DeepCopyInto(out *MongodbDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MongodbDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -3857,6 +4048,43 @@ func (in *SqlDatabaseContainerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerOperatorSpec. +func (in *SqlDatabaseContainerOperatorSpec) DeepCopy() *SqlDatabaseContainerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure) { *out = *in @@ -3916,6 +4144,43 @@ func (in *SqlDatabaseContainerStoredProcedureList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerStoredProcedureOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerStoredProcedureOperatorSpec. +func (in *SqlDatabaseContainerStoredProcedureOperatorSpec) DeepCopy() *SqlDatabaseContainerStoredProcedureOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerStoredProcedureOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerStoredProcedure_STATUS) DeepCopyInto(out *SqlDatabaseContainerStoredProcedure_STATUS) { *out = *in @@ -3978,6 +4243,11 @@ func (in *SqlDatabaseContainerStoredProcedure_Spec) DeepCopyInto(out *SqlDatabas *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerStoredProcedureOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4071,6 +4341,43 @@ func (in *SqlDatabaseContainerThroughputSettingList) DeepCopyObject() runtime.Ob return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerThroughputSettingOperatorSpec. +func (in *SqlDatabaseContainerThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseContainerThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseContainerThroughputSetting_STATUS) { *out = *in @@ -4133,6 +4440,11 @@ func (in *SqlDatabaseContainerThroughputSetting_Spec) DeepCopyInto(out *SqlDatab *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4221,6 +4533,43 @@ func (in *SqlDatabaseContainerTriggerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerTriggerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerTriggerOperatorSpec. +func (in *SqlDatabaseContainerTriggerOperatorSpec) DeepCopy() *SqlDatabaseContainerTriggerOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerTriggerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerTrigger_STATUS) DeepCopyInto(out *SqlDatabaseContainerTrigger_STATUS) { *out = *in @@ -4283,6 +4632,11 @@ func (in *SqlDatabaseContainerTrigger_Spec) DeepCopyInto(out *SqlDatabaseContain *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerTriggerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4376,6 +4730,43 @@ func (in *SqlDatabaseContainerUserDefinedFunctionList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseContainerUserDefinedFunctionOperatorSpec. +func (in *SqlDatabaseContainerUserDefinedFunctionOperatorSpec) DeepCopy() *SqlDatabaseContainerUserDefinedFunctionOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseContainerUserDefinedFunction_STATUS) DeepCopyInto(out *SqlDatabaseContainerUserDefinedFunction_STATUS) { *out = *in @@ -4438,6 +4829,11 @@ func (in *SqlDatabaseContainerUserDefinedFunction_Spec) DeepCopyInto(out *SqlDat *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerUserDefinedFunctionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4539,6 +4935,11 @@ func (in *SqlDatabaseContainer_Spec) DeepCopyInto(out *SqlDatabaseContainer_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -4660,6 +5061,43 @@ func (in *SqlDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseOperatorSpec) DeepCopyInto(out *SqlDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseOperatorSpec. +func (in *SqlDatabaseOperatorSpec) DeepCopy() *SqlDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseResource) DeepCopyInto(out *SqlDatabaseResource) { *out = *in @@ -4749,6 +5187,43 @@ func (in *SqlDatabaseThroughputSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopyInto(out *SqlDatabaseThroughputSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlDatabaseThroughputSettingOperatorSpec. +func (in *SqlDatabaseThroughputSettingOperatorSpec) DeepCopy() *SqlDatabaseThroughputSettingOperatorSpec { + if in == nil { + return nil + } + out := new(SqlDatabaseThroughputSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlDatabaseThroughputSetting_STATUS) DeepCopyInto(out *SqlDatabaseThroughputSetting_STATUS) { *out = *in @@ -4811,6 +5286,11 @@ func (in *SqlDatabaseThroughputSetting_Spec) DeepCopyInto(out *SqlDatabaseThroug *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseThroughputSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4907,6 +5387,11 @@ func (in *SqlDatabase_Spec) DeepCopyInto(out *SqlDatabase_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Options != nil { in, out := &in.Options, &out.Options *out = new(CreateUpdateOptions) @@ -5000,6 +5485,43 @@ func (in *SqlRoleAssignmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopyInto(out *SqlRoleAssignmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SqlRoleAssignmentOperatorSpec. +func (in *SqlRoleAssignmentOperatorSpec) DeepCopy() *SqlRoleAssignmentOperatorSpec { + if in == nil { + return nil + } + out := new(SqlRoleAssignmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_STATUS) DeepCopyInto(out *SqlRoleAssignment_STATUS) { *out = *in @@ -5055,6 +5577,11 @@ func (in *SqlRoleAssignment_STATUS) DeepCopy() *SqlRoleAssignment_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SqlRoleAssignment_Spec) DeepCopyInto(out *SqlRoleAssignment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SqlRoleAssignmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/eventgrid/v1api20200601/domain_types_gen.go b/v2/api/eventgrid/v1api20200601/domain_types_gen.go index 153d08810ce..2ca262d0383 100644 --- a/v2/api/eventgrid/v1api20200601/domain_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/domain_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (domain *Domain) defaultAzureName() { // defaultImpl applies the code generated defaults to the Domain resource func (domain *Domain) defaultImpl() { domain.defaultAzureName() } +var _ configmaps.Exporter = &Domain{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (domain *Domain) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Domain{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (domain *Domain) SecretDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Domain{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (domain *Domain) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (domain *Domain) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){domain.validateResourceReferences, domain.validateOwnerReference} + return []func() (admission.Warnings, error){domain.validateResourceReferences, domain.validateOwnerReference, domain.validateSecretDestinations, domain.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (domain *Domain) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return domain.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return domain.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return domain.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (domain *Domain) validateConfigMapDestinations() (admission.Warnings, error) { + if domain.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(domain, nil, domain.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (domain *Domain) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (domain *Domain) validateSecretDestinations() (admission.Warnings, error) { + if domain.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(domain, nil, domain.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (domain *Domain) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Domain) @@ -349,6 +394,10 @@ type Domain_Spec struct { // Location: Location of the resource. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DomainOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -486,6 +535,8 @@ func (domain *Domain_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefere domain.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": domain.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -613,6 +664,18 @@ func (domain *Domain_Spec) AssignProperties_From_Domain_Spec(source *storage.Dom // Location domain.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DomainOperatorSpec + err := operatorSpec.AssignProperties_From_DomainOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DomainOperatorSpec() to populate field OperatorSpec") + } + domain.OperatorSpec = &operatorSpec + } else { + domain.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -686,6 +749,18 @@ func (domain *Domain_Spec) AssignProperties_To_Domain_Spec(destination *storage. // Location destination.Location = genruntime.ClonePointerToString(domain.Location) + // OperatorSpec + if domain.OperatorSpec != nil { + var operatorSpec storage.DomainOperatorSpec + err := domain.OperatorSpec.AssignProperties_To_DomainOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DomainOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = domain.OriginalVersion() @@ -1283,6 +1358,110 @@ func (domain *Domain_STATUS) AssignProperties_To_Domain_STATUS(destination *stor return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DomainOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DomainOperatorSpec populates our DomainOperatorSpec from the provided source DomainOperatorSpec +func (operator *DomainOperatorSpec) AssignProperties_From_DomainOperatorSpec(source *storage.DomainOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DomainOperatorSpec populates the provided destination DomainOperatorSpec from our DomainOperatorSpec +func (operator *DomainOperatorSpec) AssignProperties_To_DomainOperatorSpec(destination *storage.DomainOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"CloudEventSchemaV1_0","CustomEventSchema","EventGridSchema"} type DomainProperties_InputSchema string diff --git a/v2/api/eventgrid/v1api20200601/domain_types_gen_test.go b/v2/api/eventgrid/v1api20200601/domain_types_gen_test.go index 574dddce247..67469eab775 100644 --- a/v2/api/eventgrid/v1api20200601/domain_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/domain_types_gen_test.go @@ -164,6 +164,102 @@ func AddRelatedPropertyGeneratorsForDomain(gens map[string]gopter.Gen) { gens["Status"] = Domain_STATUSGenerator() } +func Test_DomainOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DomainOperatorSpec to DomainOperatorSpec via AssignProperties_To_DomainOperatorSpec & AssignProperties_From_DomainOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDomainOperatorSpec, DomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDomainOperatorSpec tests if a specific instance of DomainOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDomainOperatorSpec(subject DomainOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DomainOperatorSpec + err := copied.AssignProperties_To_DomainOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DomainOperatorSpec + err = actual.AssignProperties_From_DomainOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DomainOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DomainOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDomainOperatorSpec, DomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDomainOperatorSpec runs a test to see if a specific instance of DomainOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDomainOperatorSpec(subject DomainOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DomainOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DomainOperatorSpec instances for property testing - lazily instantiated by DomainOperatorSpecGenerator() +var domainOperatorSpecGenerator gopter.Gen + +// DomainOperatorSpecGenerator returns a generator of DomainOperatorSpec instances for property testing. +func DomainOperatorSpecGenerator() gopter.Gen { + if domainOperatorSpecGenerator != nil { + return domainOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + domainOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DomainOperatorSpec{}), generators) + + return domainOperatorSpecGenerator +} + func Test_Domain_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +517,7 @@ func AddIndependentPropertyGeneratorsForDomain_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForDomain_Spec(gens map[string]gopter.Gen) { gens["InboundIpRules"] = gen.SliceOf(InboundIpRuleGenerator()) gens["InputSchemaMapping"] = gen.PtrOf(InputSchemaMappingGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DomainOperatorSpecGenerator()) } func Test_InboundIpRule_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/eventgrid/v1api20200601/domains_topic_types_gen.go b/v2/api/eventgrid/v1api20200601/domains_topic_types_gen.go index ecc75bbc7c0..92471efaba7 100644 --- a/v2/api/eventgrid/v1api20200601/domains_topic_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/domains_topic_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (topic *DomainsTopic) defaultAzureName() { // defaultImpl applies the code generated defaults to the DomainsTopic resource func (topic *DomainsTopic) defaultImpl() { topic.defaultAzureName() } +var _ configmaps.Exporter = &DomainsTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *DomainsTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DomainsTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *DomainsTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DomainsTopic{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (topic *DomainsTopic) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (topic *DomainsTopic) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference} + return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference, topic.validateSecretDestinations, topic.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (topic *DomainsTopic) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return topic.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (topic *DomainsTopic) validateConfigMapDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (topic *DomainsTopic) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (topic *DomainsTopic) validateSecretDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (topic *DomainsTopic) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DomainsTopic) @@ -330,6 +375,10 @@ type DomainsTopic_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DomainsTopicOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -366,6 +415,8 @@ func (topic *DomainsTopic_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR // Set property "AzureName": topic.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": topic.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -432,6 +483,18 @@ func (topic *DomainsTopic_Spec) AssignProperties_From_DomainsTopic_Spec(source * // AzureName topic.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DomainsTopicOperatorSpec + err := operatorSpec.AssignProperties_From_DomainsTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DomainsTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -452,6 +515,18 @@ func (topic *DomainsTopic_Spec) AssignProperties_To_DomainsTopic_Spec(destinatio // AzureName destination.AzureName = topic.AzureName + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.DomainsTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_DomainsTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DomainsTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion() @@ -707,6 +782,110 @@ func (topic *DomainsTopic_STATUS) AssignProperties_To_DomainsTopic_STATUS(destin return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DomainsTopicOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DomainsTopicOperatorSpec populates our DomainsTopicOperatorSpec from the provided source DomainsTopicOperatorSpec +func (operator *DomainsTopicOperatorSpec) AssignProperties_From_DomainsTopicOperatorSpec(source *storage.DomainsTopicOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DomainsTopicOperatorSpec populates the provided destination DomainsTopicOperatorSpec from our DomainsTopicOperatorSpec +func (operator *DomainsTopicOperatorSpec) AssignProperties_To_DomainsTopicOperatorSpec(destination *storage.DomainsTopicOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type DomainTopicProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/eventgrid/v1api20200601/domains_topic_types_gen_test.go b/v2/api/eventgrid/v1api20200601/domains_topic_types_gen_test.go index 89846fbccfd..ff3ce360b49 100644 --- a/v2/api/eventgrid/v1api20200601/domains_topic_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/domains_topic_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDomainsTopic(gens map[string]gopter.Gen) { gens["Status"] = DomainsTopic_STATUSGenerator() } +func Test_DomainsTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DomainsTopicOperatorSpec to DomainsTopicOperatorSpec via AssignProperties_To_DomainsTopicOperatorSpec & AssignProperties_From_DomainsTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDomainsTopicOperatorSpec, DomainsTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDomainsTopicOperatorSpec tests if a specific instance of DomainsTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDomainsTopicOperatorSpec(subject DomainsTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DomainsTopicOperatorSpec + err := copied.AssignProperties_To_DomainsTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DomainsTopicOperatorSpec + err = actual.AssignProperties_From_DomainsTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DomainsTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DomainsTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDomainsTopicOperatorSpec, DomainsTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDomainsTopicOperatorSpec runs a test to see if a specific instance of DomainsTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDomainsTopicOperatorSpec(subject DomainsTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DomainsTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DomainsTopicOperatorSpec instances for property testing - lazily instantiated by +// DomainsTopicOperatorSpecGenerator() +var domainsTopicOperatorSpecGenerator gopter.Gen + +// DomainsTopicOperatorSpecGenerator returns a generator of DomainsTopicOperatorSpec instances for property testing. +func DomainsTopicOperatorSpecGenerator() gopter.Gen { + if domainsTopicOperatorSpecGenerator != nil { + return domainsTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + domainsTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopicOperatorSpec{}), generators) + + return domainsTopicOperatorSpecGenerator +} + func Test_DomainsTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -375,6 +472,9 @@ func RunJSONSerializationTestForDomainsTopic_Spec(subject DomainsTopic_Spec) str var domainsTopic_SpecGenerator gopter.Gen // DomainsTopic_SpecGenerator returns a generator of DomainsTopic_Spec instances for property testing. +// We first initialize domainsTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func DomainsTopic_SpecGenerator() gopter.Gen { if domainsTopic_SpecGenerator != nil { return domainsTopic_SpecGenerator @@ -384,6 +484,12 @@ func DomainsTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForDomainsTopic_Spec(generators) domainsTopic_SpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForDomainsTopic_Spec(generators) + AddRelatedPropertyGeneratorsForDomainsTopic_Spec(generators) + domainsTopic_SpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopic_Spec{}), generators) + return domainsTopic_SpecGenerator } @@ -391,3 +497,8 @@ func DomainsTopic_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForDomainsTopic_Spec(gens map[string]gopter.Gen) { gens["AzureName"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForDomainsTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForDomainsTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DomainsTopicOperatorSpecGenerator()) +} diff --git a/v2/api/eventgrid/v1api20200601/event_subscription_types_gen.go b/v2/api/eventgrid/v1api20200601/event_subscription_types_gen.go index 6f249ac6b62..c1ef32c9783 100644 --- a/v2/api/eventgrid/v1api20200601/event_subscription_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/event_subscription_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (subscription *EventSubscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the EventSubscription resource func (subscription *EventSubscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &EventSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *EventSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &EventSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *EventSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &EventSubscription{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (subscription *EventSubscription) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (subscription *EventSubscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,22 @@ func (subscription *EventSubscription) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return subscription.validateResourceReferences() }, - subscription.validateWriteOnceProperties} + subscription.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *EventSubscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -234,6 +272,14 @@ func (subscription *EventSubscription) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (subscription *EventSubscription) validateSecretDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (subscription *EventSubscription) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*EventSubscription) @@ -338,6 +384,10 @@ type EventSubscription_Spec struct { // Labels: List of user defined labels. Labels []string `json:"labels,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *EventSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. This resource is an @@ -504,6 +554,8 @@ func (subscription *EventSubscription_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": subscription.Owner = &owner @@ -632,6 +684,18 @@ func (subscription *EventSubscription_Spec) AssignProperties_From_EventSubscript // Labels subscription.Labels = genruntime.CloneSliceOfString(source.Labels) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec EventSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_EventSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_EventSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -714,6 +778,18 @@ func (subscription *EventSubscription_Spec) AssignProperties_To_EventSubscriptio // Labels destination.Labels = genruntime.CloneSliceOfString(subscription.Labels) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.EventSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_EventSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_EventSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion() @@ -2700,6 +2776,110 @@ func (filter *EventSubscriptionFilter_STATUS) AssignProperties_To_EventSubscript return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type EventSubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_EventSubscriptionOperatorSpec populates our EventSubscriptionOperatorSpec from the provided source EventSubscriptionOperatorSpec +func (operator *EventSubscriptionOperatorSpec) AssignProperties_From_EventSubscriptionOperatorSpec(source *storage.EventSubscriptionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_EventSubscriptionOperatorSpec populates the provided destination EventSubscriptionOperatorSpec from our EventSubscriptionOperatorSpec +func (operator *EventSubscriptionOperatorSpec) AssignProperties_To_EventSubscriptionOperatorSpec(destination *storage.EventSubscriptionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"CloudEventSchemaV1_0","CustomInputSchema","EventGridSchema"} type EventSubscriptionProperties_EventDeliverySchema string diff --git a/v2/api/eventgrid/v1api20200601/event_subscription_types_gen_test.go b/v2/api/eventgrid/v1api20200601/event_subscription_types_gen_test.go index 1776c83cb18..3f8d74e17e5 100644 --- a/v2/api/eventgrid/v1api20200601/event_subscription_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/event_subscription_types_gen_test.go @@ -1799,6 +1799,103 @@ func AddRelatedPropertyGeneratorsForEventSubscriptionFilter_STATUS(gens map[stri gens["AdvancedFilters"] = gen.SliceOf(AdvancedFilter_STATUSGenerator()) } +func Test_EventSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from EventSubscriptionOperatorSpec to EventSubscriptionOperatorSpec via AssignProperties_To_EventSubscriptionOperatorSpec & AssignProperties_From_EventSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForEventSubscriptionOperatorSpec, EventSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForEventSubscriptionOperatorSpec tests if a specific instance of EventSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForEventSubscriptionOperatorSpec(subject EventSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.EventSubscriptionOperatorSpec + err := copied.AssignProperties_To_EventSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual EventSubscriptionOperatorSpec + err = actual.AssignProperties_From_EventSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_EventSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of EventSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForEventSubscriptionOperatorSpec, EventSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForEventSubscriptionOperatorSpec runs a test to see if a specific instance of EventSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForEventSubscriptionOperatorSpec(subject EventSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual EventSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of EventSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// EventSubscriptionOperatorSpecGenerator() +var eventSubscriptionOperatorSpecGenerator gopter.Gen + +// EventSubscriptionOperatorSpecGenerator returns a generator of EventSubscriptionOperatorSpec instances for property testing. +func EventSubscriptionOperatorSpecGenerator() gopter.Gen { + if eventSubscriptionOperatorSpecGenerator != nil { + return eventSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + eventSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(EventSubscriptionOperatorSpec{}), generators) + + return eventSubscriptionOperatorSpecGenerator +} + func Test_EventSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2054,6 +2151,7 @@ func AddRelatedPropertyGeneratorsForEventSubscription_Spec(gens map[string]gopte gens["DeadLetterDestination"] = gen.PtrOf(DeadLetterDestinationGenerator()) gens["Destination"] = gen.PtrOf(EventSubscriptionDestinationGenerator()) gens["Filter"] = gen.PtrOf(EventSubscriptionFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(EventSubscriptionOperatorSpecGenerator()) gens["RetryPolicy"] = gen.PtrOf(RetryPolicyGenerator()) } diff --git a/v2/api/eventgrid/v1api20200601/storage/domain_types_gen.go b/v2/api/eventgrid/v1api20200601/storage/domain_types_gen.go index dc6e81ecae2..7bd464977a9 100644 --- a/v2/api/eventgrid/v1api20200601/storage/domain_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/storage/domain_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (domain *Domain) SetConditions(conditions conditions.Conditions) { domain.Status.Conditions = conditions } +var _ configmaps.Exporter = &Domain{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (domain *Domain) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Domain{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (domain *Domain) SecretDestinationExpressions() []*core.DestinationExpression { + if domain.Spec.OperatorSpec == nil { + return nil + } + return domain.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Domain{} // AzureName returns the Azure name of the resource @@ -153,6 +176,7 @@ type Domain_Spec struct { InputSchema *string `json:"inputSchema,omitempty"` InputSchemaMapping *InputSchemaMapping `json:"inputSchemaMapping,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *DomainOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -226,6 +250,14 @@ func (domain *Domain_STATUS) ConvertStatusTo(destination genruntime.ConvertibleS return destination.ConvertStatusFrom(domain) } +// Storage version of v1api20200601.DomainOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DomainOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20200601.InboundIpRule type InboundIpRule struct { Action *string `json:"action,omitempty"` diff --git a/v2/api/eventgrid/v1api20200601/storage/domain_types_gen_test.go b/v2/api/eventgrid/v1api20200601/storage/domain_types_gen_test.go index fa63ab66b8d..b0bb4f6d0bf 100644 --- a/v2/api/eventgrid/v1api20200601/storage/domain_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/storage/domain_types_gen_test.go @@ -78,6 +78,60 @@ func AddRelatedPropertyGeneratorsForDomain(gens map[string]gopter.Gen) { gens["Status"] = Domain_STATUSGenerator() } +func Test_DomainOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DomainOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDomainOperatorSpec, DomainOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDomainOperatorSpec runs a test to see if a specific instance of DomainOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDomainOperatorSpec(subject DomainOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DomainOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DomainOperatorSpec instances for property testing - lazily instantiated by DomainOperatorSpecGenerator() +var domainOperatorSpecGenerator gopter.Gen + +// DomainOperatorSpecGenerator returns a generator of DomainOperatorSpec instances for property testing. +func DomainOperatorSpecGenerator() gopter.Gen { + if domainOperatorSpecGenerator != nil { + return domainOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + domainOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DomainOperatorSpec{}), generators) + + return domainOperatorSpecGenerator +} + func Test_Domain_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -246,6 +300,7 @@ func AddIndependentPropertyGeneratorsForDomain_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForDomain_Spec(gens map[string]gopter.Gen) { gens["InboundIpRules"] = gen.SliceOf(InboundIpRuleGenerator()) gens["InputSchemaMapping"] = gen.PtrOf(InputSchemaMappingGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DomainOperatorSpecGenerator()) } func Test_InboundIpRule_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen.go b/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen.go index ccedde5d23e..3ea4637e967 100644 --- a/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (topic *DomainsTopic) SetConditions(conditions conditions.Conditions) { topic.Status.Conditions = conditions } +var _ configmaps.Exporter = &DomainsTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *DomainsTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DomainsTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *DomainsTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DomainsTopic{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type DomainsTopicList struct { type DomainsTopic_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *DomainsTopicOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -204,6 +228,14 @@ func (topic *DomainsTopic_STATUS) ConvertStatusTo(destination genruntime.Convert return destination.ConvertStatusFrom(topic) } +// Storage version of v1api20200601.DomainsTopicOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DomainsTopicOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DomainsTopic{}, &DomainsTopicList{}) } diff --git a/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen_test.go b/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen_test.go index e0d30825a28..7ed45552a6c 100644 --- a/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/storage/domains_topic_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDomainsTopic(gens map[string]gopter.Gen) { gens["Status"] = DomainsTopic_STATUSGenerator() } +func Test_DomainsTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DomainsTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDomainsTopicOperatorSpec, DomainsTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDomainsTopicOperatorSpec runs a test to see if a specific instance of DomainsTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDomainsTopicOperatorSpec(subject DomainsTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DomainsTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DomainsTopicOperatorSpec instances for property testing - lazily instantiated by +// DomainsTopicOperatorSpecGenerator() +var domainsTopicOperatorSpecGenerator gopter.Gen + +// DomainsTopicOperatorSpecGenerator returns a generator of DomainsTopicOperatorSpec instances for property testing. +func DomainsTopicOperatorSpecGenerator() gopter.Gen { + if domainsTopicOperatorSpecGenerator != nil { + return domainsTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + domainsTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopicOperatorSpec{}), generators) + + return domainsTopicOperatorSpecGenerator +} + func Test_DomainsTopic_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -199,6 +254,9 @@ func RunJSONSerializationTestForDomainsTopic_Spec(subject DomainsTopic_Spec) str var domainsTopic_SpecGenerator gopter.Gen // DomainsTopic_SpecGenerator returns a generator of DomainsTopic_Spec instances for property testing. +// We first initialize domainsTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func DomainsTopic_SpecGenerator() gopter.Gen { if domainsTopic_SpecGenerator != nil { return domainsTopic_SpecGenerator @@ -208,6 +266,12 @@ func DomainsTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForDomainsTopic_Spec(generators) domainsTopic_SpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForDomainsTopic_Spec(generators) + AddRelatedPropertyGeneratorsForDomainsTopic_Spec(generators) + domainsTopic_SpecGenerator = gen.Struct(reflect.TypeOf(DomainsTopic_Spec{}), generators) + return domainsTopic_SpecGenerator } @@ -216,3 +280,8 @@ func AddIndependentPropertyGeneratorsForDomainsTopic_Spec(gens map[string]gopter gens["AzureName"] = gen.AlphaString() gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForDomainsTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForDomainsTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DomainsTopicOperatorSpecGenerator()) +} diff --git a/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen.go b/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen.go index 433e86667b7..758646cbb8f 100644 --- a/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (subscription *EventSubscription) SetConditions(conditions conditions.Condi subscription.Status.Conditions = conditions } +var _ configmaps.Exporter = &EventSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *EventSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &EventSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *EventSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &EventSubscription{} // AzureName returns the Azure name of the resource @@ -141,14 +164,15 @@ type EventSubscriptionList struct { type EventSubscription_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DeadLetterDestination *DeadLetterDestination `json:"deadLetterDestination,omitempty"` - Destination *EventSubscriptionDestination `json:"destination,omitempty"` - EventDeliverySchema *string `json:"eventDeliverySchema,omitempty"` - ExpirationTimeUtc *string `json:"expirationTimeUtc,omitempty"` - Filter *EventSubscriptionFilter `json:"filter,omitempty"` - Labels []string `json:"labels,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DeadLetterDestination *DeadLetterDestination `json:"deadLetterDestination,omitempty"` + Destination *EventSubscriptionDestination `json:"destination,omitempty"` + EventDeliverySchema *string `json:"eventDeliverySchema,omitempty"` + ExpirationTimeUtc *string `json:"expirationTimeUtc,omitempty"` + Filter *EventSubscriptionFilter `json:"filter,omitempty"` + Labels []string `json:"labels,omitempty"` + OperatorSpec *EventSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -277,6 +301,14 @@ type EventSubscriptionFilter_STATUS struct { SubjectEndsWith *string `json:"subjectEndsWith,omitempty"` } +// Storage version of v1api20200601.EventSubscriptionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type EventSubscriptionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20200601.RetryPolicy // Information about the retry policy for an event subscription. type RetryPolicy struct { diff --git a/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen_test.go b/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen_test.go index 4940913c2a6..968db9c9740 100644 --- a/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen_test.go +++ b/v2/api/eventgrid/v1api20200601/storage/event_subscription_types_gen_test.go @@ -1125,6 +1125,61 @@ func AddRelatedPropertyGeneratorsForEventSubscriptionFilter_STATUS(gens map[stri gens["AdvancedFilters"] = gen.SliceOf(AdvancedFilter_STATUSGenerator()) } +func Test_EventSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of EventSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForEventSubscriptionOperatorSpec, EventSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForEventSubscriptionOperatorSpec runs a test to see if a specific instance of EventSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForEventSubscriptionOperatorSpec(subject EventSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual EventSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of EventSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// EventSubscriptionOperatorSpecGenerator() +var eventSubscriptionOperatorSpecGenerator gopter.Gen + +// EventSubscriptionOperatorSpecGenerator returns a generator of EventSubscriptionOperatorSpec instances for property testing. +func EventSubscriptionOperatorSpecGenerator() gopter.Gen { + if eventSubscriptionOperatorSpecGenerator != nil { + return eventSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + eventSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(EventSubscriptionOperatorSpec{}), generators) + + return eventSubscriptionOperatorSpecGenerator +} + func Test_EventSubscription_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1290,6 +1345,7 @@ func AddRelatedPropertyGeneratorsForEventSubscription_Spec(gens map[string]gopte gens["DeadLetterDestination"] = gen.PtrOf(DeadLetterDestinationGenerator()) gens["Destination"] = gen.PtrOf(EventSubscriptionDestinationGenerator()) gens["Filter"] = gen.PtrOf(EventSubscriptionFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(EventSubscriptionOperatorSpecGenerator()) gens["RetryPolicy"] = gen.PtrOf(RetryPolicyGenerator()) } diff --git a/v2/api/eventgrid/v1api20200601/storage/structure.txt b/v2/api/eventgrid/v1api20200601/storage/structure.txt index a4e037fc732..85010f7c7d6 100644 --- a/v2/api/eventgrid/v1api20200601/storage/structure.txt +++ b/v2/api/eventgrid/v1api20200601/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-06-01" Domain: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: string │ ├── InboundIpRules: Object (3 properties)[] │ │ ├── Action: *string @@ -39,6 +39,10 @@ Domain: Resource │ │ │ └── SourceField: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -100,8 +104,12 @@ Domain: Resource └── Type: *string DomainsTopic: Resource ├── Owner: eventgrid/v1api20200601.Domain -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -121,7 +129,7 @@ DomainsTopic: Resource │ └── PropertyBag: genruntime.PropertyBag └── Type: *string EventSubscription: Resource -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── DeadLetterDestination: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -238,6 +246,10 @@ EventSubscription: Resource │ │ ├── SubjectBeginsWith: *string │ │ └── SubjectEndsWith: *string │ ├── Labels: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PropertyBag: genruntime.PropertyBag @@ -416,11 +428,13 @@ Topic: Resource │ │ │ └── SourceField: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Location: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── Endpoint: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── Key1: *genruntime.SecretDestination │ │ ├── Key2: *genruntime.SecretDestination diff --git a/v2/api/eventgrid/v1api20200601/storage/topic_types_gen.go b/v2/api/eventgrid/v1api20200601/storage/topic_types_gen.go index c03e7934b42..11c27139e75 100644 --- a/v2/api/eventgrid/v1api20200601/storage/topic_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/storage/topic_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (topic *Topic) SetConditions(conditions conditions.Conditions) { topic.Status.Conditions = conditions } +var _ configmaps.Exporter = &Topic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *Topic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Topic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *Topic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Topic{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -252,9 +274,11 @@ type PrivateEndpointConnection_STATUS_Topic_SubResourceEmbedded struct { // Storage version of v1api20200601.TopicOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type TopicOperatorSpec struct { - ConfigMaps *TopicOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *TopicOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *TopicOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *TopicOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20200601.TopicOperatorConfigMaps diff --git a/v2/api/eventgrid/v1api20200601/storage/zz_generated.deepcopy.go b/v2/api/eventgrid/v1api20200601/storage/zz_generated.deepcopy.go index a818b496319..29d51fe5982 100644 --- a/v2/api/eventgrid/v1api20200601/storage/zz_generated.deepcopy.go +++ b/v2/api/eventgrid/v1api20200601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -450,6 +451,50 @@ func (in *DomainList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainOperatorSpec) DeepCopyInto(out *DomainOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainOperatorSpec. +func (in *DomainOperatorSpec) DeepCopy() *DomainOperatorSpec { + if in == nil { + return nil + } + out := new(DomainOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Domain_STATUS) DeepCopyInto(out *Domain_STATUS) { *out = *in @@ -580,6 +625,11 @@ func (in *Domain_Spec) DeepCopyInto(out *Domain_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DomainOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -675,6 +725,50 @@ func (in *DomainsTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainsTopicOperatorSpec) DeepCopyInto(out *DomainsTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainsTopicOperatorSpec. +func (in *DomainsTopicOperatorSpec) DeepCopy() *DomainsTopicOperatorSpec { + if in == nil { + return nil + } + out := new(DomainsTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DomainsTopic_STATUS) DeepCopyInto(out *DomainsTopic_STATUS) { *out = *in @@ -732,6 +826,11 @@ func (in *DomainsTopic_STATUS) DeepCopy() *DomainsTopic_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DomainsTopic_Spec) DeepCopyInto(out *DomainsTopic_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DomainsTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1091,6 +1190,50 @@ func (in *EventSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventSubscriptionOperatorSpec) DeepCopyInto(out *EventSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventSubscriptionOperatorSpec. +func (in *EventSubscriptionOperatorSpec) DeepCopy() *EventSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(EventSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EventSubscription_STATUS) DeepCopyInto(out *EventSubscription_STATUS) { *out = *in @@ -1218,6 +1361,11 @@ func (in *EventSubscription_Spec) DeepCopyInto(out *EventSubscription_Spec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(EventSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) @@ -3042,6 +3190,17 @@ func (in *TopicOperatorSecrets) DeepCopy() *TopicOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TopicOperatorSpec) DeepCopyInto(out *TopicOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(TopicOperatorConfigMaps) @@ -3054,6 +3213,17 @@ func (in *TopicOperatorSpec) DeepCopyInto(out *TopicOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(TopicOperatorSecrets) diff --git a/v2/api/eventgrid/v1api20200601/structure.txt b/v2/api/eventgrid/v1api20200601/structure.txt index bb516fba626..eb365dd0146 100644 --- a/v2/api/eventgrid/v1api20200601/structure.txt +++ b/v2/api/eventgrid/v1api20200601/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-06-01" Domain: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── InboundIpRules: Object (2 properties)[] │ │ ├── Action: *Enum (1 value) @@ -35,6 +35,9 @@ Domain: Resource │ │ └── Topic: *Object (1 property) │ │ └── SourceField: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" @@ -105,8 +108,11 @@ Domain: Resource └── Type: *string DomainsTopic: Resource ├── Owner: Domain -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (6 properties) ├── Conditions: conditions.Condition[] @@ -136,7 +142,7 @@ DomainsTopic: Resource │ └── "User" └── Type: *string EventSubscription: Resource -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── DeadLetterDestination: *Object (1 property) │ │ └── StorageBlob: *Object (3 properties) @@ -252,6 +258,9 @@ EventSubscription: Resource │ │ ├── SubjectBeginsWith: *string │ │ └── SubjectEndsWith: *string │ ├── Labels: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ └── RetryPolicy: *Object (2 properties) │ ├── EventTimeToLiveInMinutes: *int @@ -434,9 +443,11 @@ Topic: Resource │ │ └── Topic: *Object (1 property) │ │ └── SourceField: *string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (1 property) │ │ │ └── Endpoint: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (2 properties) │ │ ├── Key1: *genruntime.SecretDestination │ │ └── Key2: *genruntime.SecretDestination diff --git a/v2/api/eventgrid/v1api20200601/topic_types_gen.go b/v2/api/eventgrid/v1api20200601/topic_types_gen.go index 6c8b12eb209..55e4293bef4 100644 --- a/v2/api/eventgrid/v1api20200601/topic_types_gen.go +++ b/v2/api/eventgrid/v1api20200601/topic_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -97,6 +98,26 @@ func (topic *Topic) defaultAzureName() { // defaultImpl applies the code generated defaults to the Topic resource func (topic *Topic) defaultImpl() { topic.defaultAzureName() } +var _ configmaps.Exporter = &Topic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *Topic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Topic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *Topic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Topic{} // InitializeSpec initializes the spec for this resource from the given status @@ -264,13 +285,13 @@ func (topic *Topic) validateConfigMapDestinations() (admission.Warnings, error) if topic.Spec.OperatorSpec == nil { return nil, nil } - if topic.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - topic.Spec.OperatorSpec.ConfigMaps.Endpoint, + var toValidate []*genruntime.ConfigMapDestination + if topic.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + topic.Spec.OperatorSpec.ConfigMaps.Endpoint, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(topic, toValidate, topic.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -292,14 +313,14 @@ func (topic *Topic) validateSecretDestinations() (admission.Warnings, error) { if topic.Spec.OperatorSpec == nil { return nil, nil } - if topic.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - topic.Spec.OperatorSpec.Secrets.Key1, - topic.Spec.OperatorSpec.Secrets.Key2, + var toValidate []*genruntime.SecretDestination + if topic.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + topic.Spec.OperatorSpec.Secrets.Key1, + topic.Spec.OperatorSpec.Secrets.Key2, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(topic, toValidate, topic.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1426,9 +1447,15 @@ func (embedded *PrivateEndpointConnection_STATUS_Topic_SubResourceEmbedded) Assi // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type TopicOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *TopicOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *TopicOperatorSecrets `json:"secrets,omitempty"` } @@ -1436,6 +1463,24 @@ type TopicOperatorSpec struct { // AssignProperties_From_TopicOperatorSpec populates our TopicOperatorSpec from the provided source TopicOperatorSpec func (operator *TopicOperatorSpec) AssignProperties_From_TopicOperatorSpec(source *storage.TopicOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap TopicOperatorConfigMaps @@ -1448,6 +1493,24 @@ func (operator *TopicOperatorSpec) AssignProperties_From_TopicOperatorSpec(sourc operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret TopicOperatorSecrets @@ -1469,6 +1532,24 @@ func (operator *TopicOperatorSpec) AssignProperties_To_TopicOperatorSpec(destina // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.TopicOperatorConfigMaps @@ -1481,6 +1562,24 @@ func (operator *TopicOperatorSpec) AssignProperties_To_TopicOperatorSpec(destina destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.TopicOperatorSecrets diff --git a/v2/api/eventgrid/v1api20200601/zz_generated.deepcopy.go b/v2/api/eventgrid/v1api20200601/zz_generated.deepcopy.go index ad589dc04bf..0042cac0008 100644 --- a/v2/api/eventgrid/v1api20200601/zz_generated.deepcopy.go +++ b/v2/api/eventgrid/v1api20200601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20200601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -394,6 +395,43 @@ func (in *DomainList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainOperatorSpec) DeepCopyInto(out *DomainOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainOperatorSpec. +func (in *DomainOperatorSpec) DeepCopy() *DomainOperatorSpec { + if in == nil { + return nil + } + out := new(DomainOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Domain_STATUS) DeepCopyInto(out *Domain_STATUS) { *out = *in @@ -517,6 +555,11 @@ func (in *Domain_Spec) DeepCopyInto(out *Domain_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DomainOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -605,6 +648,43 @@ func (in *DomainsTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DomainsTopicOperatorSpec) DeepCopyInto(out *DomainsTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DomainsTopicOperatorSpec. +func (in *DomainsTopicOperatorSpec) DeepCopy() *DomainsTopicOperatorSpec { + if in == nil { + return nil + } + out := new(DomainsTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DomainsTopic_STATUS) DeepCopyInto(out *DomainsTopic_STATUS) { *out = *in @@ -655,6 +735,11 @@ func (in *DomainsTopic_STATUS) DeepCopy() *DomainsTopic_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DomainsTopic_Spec) DeepCopyInto(out *DomainsTopic_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DomainsTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -965,6 +1050,43 @@ func (in *EventSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventSubscriptionOperatorSpec) DeepCopyInto(out *EventSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventSubscriptionOperatorSpec. +func (in *EventSubscriptionOperatorSpec) DeepCopy() *EventSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(EventSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EventSubscription_STATUS) DeepCopyInto(out *EventSubscription_STATUS) { *out = *in @@ -1085,6 +1207,11 @@ func (in *EventSubscription_Spec) DeepCopyInto(out *EventSubscription_Spec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(EventSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) @@ -2559,11 +2686,33 @@ func (in *TopicOperatorSecrets) DeepCopy() *TopicOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TopicOperatorSpec) DeepCopyInto(out *TopicOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(TopicOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(TopicOperatorSecrets) diff --git a/v2/api/eventhub/v1api20211101/namespace_types_gen.go b/v2/api/eventhub/v1api20211101/namespace_types_gen.go index 1d4eadbe916..7f328f314c1 100644 --- a/v2/api/eventhub/v1api20211101/namespace_types_gen.go +++ b/v2/api/eventhub/v1api20211101/namespace_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (namespace *Namespace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Namespace resource func (namespace *Namespace) defaultImpl() { namespace.defaultAzureName() } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Namespace{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (namespace *Namespace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (namespace *Namespace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations} + return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations, namespace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (namespace *Namespace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return namespace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return namespace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (namespace *Namespace) validateConfigMapDestinations() (admission.Warnings, error) { + if namespace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(namespace, nil, namespace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,16 +286,16 @@ func (namespace *Namespace) validateSecretDestinations() (admission.Warnings, er if namespace.Spec.OperatorSpec == nil { return nil, nil } - if namespace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.PrimaryKey, - namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if namespace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.PrimaryKey, + namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(namespace, toValidate, namespace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2394,6 +2427,12 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } @@ -2401,6 +2440,42 @@ type NamespaceOperatorSpec struct { // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSpec(source *storage.NamespaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -2422,6 +2497,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/eventhub/v1api20211101/namespaces_authorization_rule_types_gen.go b/v2/api/eventhub/v1api20211101/namespaces_authorization_rule_types_gen.go index 95bfdf4c8ba..eca3e23e05c 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_authorization_rule_types_gen.go +++ b/v2/api/eventhub/v1api20211101/namespaces_authorization_rule_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (rule *NamespacesAuthorizationRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesAuthorizationRule resource func (rule *NamespacesAuthorizationRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesAuthorizationRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (rule *NamespacesAuthorizationRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *NamespacesAuthorizationRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,9 +253,20 @@ func (rule *NamespacesAuthorizationRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesAuthorizationRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *NamespacesAuthorizationRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -253,16 +286,16 @@ func (rule *NamespacesAuthorizationRule) validateSecretDestinations() (admission if rule.Spec.OperatorSpec == nil { return nil, nil } - if rule.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - rule.Spec.OperatorSpec.Secrets.PrimaryKey, - rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - rule.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if rule.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + rule.Spec.OperatorSpec.Secrets.PrimaryKey, + rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + rule.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(rule, toValidate, rule.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -882,6 +915,12 @@ var namespaces_AuthorizationRule_Properties_Rights_STATUS_Values = map[string]Na // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } @@ -889,6 +928,42 @@ type NamespacesAuthorizationRuleOperatorSpec struct { // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec(source *storage.NamespacesAuthorizationRuleOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -910,6 +985,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen.go b/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen.go index 587f6c6d7ae..2dafe34f03a 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen.go +++ b/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (eventhub *NamespacesEventhub) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesEventhub resource func (eventhub *NamespacesEventhub) defaultImpl() { eventhub.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesEventhub{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (eventhub *NamespacesEventhub) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if eventhub.Spec.OperatorSpec == nil { + return nil + } + return eventhub.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhub{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (eventhub *NamespacesEventhub) SecretDestinationExpressions() []*core.DestinationExpression { + if eventhub.Spec.OperatorSpec == nil { + return nil + } + return eventhub.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesEventhub{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (eventhub *NamespacesEventhub) ValidateUpdate(old runtime.Object) (admissio // createValidations validates the creation of the resource func (eventhub *NamespacesEventhub) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){eventhub.validateResourceReferences, eventhub.validateOwnerReference} + return []func() (admission.Warnings, error){eventhub.validateResourceReferences, eventhub.validateOwnerReference, eventhub.validateSecretDestinations, eventhub.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (eventhub *NamespacesEventhub) updateValidations() []func(old runtime.Objec func(old runtime.Object) (admission.Warnings, error) { return eventhub.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return eventhub.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return eventhub.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (eventhub *NamespacesEventhub) validateConfigMapDestinations() (admission.Warnings, error) { + if eventhub.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(eventhub, nil, eventhub.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (eventhub *NamespacesEventhub) validateResourceReferences() (admission.Warn return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (eventhub *NamespacesEventhub) validateSecretDestinations() (admission.Warnings, error) { + if eventhub.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(eventhub, nil, eventhub.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (eventhub *NamespacesEventhub) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesEventhub) @@ -339,6 +384,10 @@ type NamespacesEventhub_Spec struct { // MessageRetentionInDays: Number of days to retain the events for this Event Hub, value should be 1 to 7 days MessageRetentionInDays *int `json:"messageRetentionInDays,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesEventhubOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -425,6 +474,8 @@ func (eventhub *NamespacesEventhub_Spec) PopulateFromARM(owner genruntime.Arbitr } } + // no assignment for property "OperatorSpec" + // Set property "Owner": eventhub.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -520,6 +571,18 @@ func (eventhub *NamespacesEventhub_Spec) AssignProperties_From_NamespacesEventhu eventhub.MessageRetentionInDays = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesEventhubOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesEventhubOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesEventhubOperatorSpec() to populate field OperatorSpec") + } + eventhub.OperatorSpec = &operatorSpec + } else { + eventhub.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -568,6 +631,18 @@ func (eventhub *NamespacesEventhub_Spec) AssignProperties_To_NamespacesEventhub_ destination.MessageRetentionInDays = nil } + // OperatorSpec + if eventhub.OperatorSpec != nil { + var operatorSpec storage.NamespacesEventhubOperatorSpec + err := eventhub.OperatorSpec.AssignProperties_To_NamespacesEventhubOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesEventhubOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = eventhub.OriginalVersion() @@ -1520,6 +1595,110 @@ var namespaces_Eventhub_Properties_Status_STATUS_Values = map[string]Namespaces_ "unknown": Namespaces_Eventhub_Properties_Status_STATUS_Unknown, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesEventhubOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesEventhubOperatorSpec populates our NamespacesEventhubOperatorSpec from the provided source NamespacesEventhubOperatorSpec +func (operator *NamespacesEventhubOperatorSpec) AssignProperties_From_NamespacesEventhubOperatorSpec(source *storage.NamespacesEventhubOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesEventhubOperatorSpec populates the provided destination NamespacesEventhubOperatorSpec from our NamespacesEventhubOperatorSpec +func (operator *NamespacesEventhubOperatorSpec) AssignProperties_To_NamespacesEventhubOperatorSpec(destination *storage.NamespacesEventhubOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Avro","AvroDeflate"} type CaptureDescription_Encoding string diff --git a/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen_test.go b/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen_test.go index 434ab03c1e8..866de463ce8 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen_test.go +++ b/v2/api/eventhub/v1api20211101/namespaces_eventhub_types_gen_test.go @@ -620,6 +620,103 @@ func AddRelatedPropertyGeneratorsForNamespacesEventhub(gens map[string]gopter.Ge gens["Status"] = NamespacesEventhub_STATUSGenerator() } +func Test_NamespacesEventhubOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesEventhubOperatorSpec to NamespacesEventhubOperatorSpec via AssignProperties_To_NamespacesEventhubOperatorSpec & AssignProperties_From_NamespacesEventhubOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesEventhubOperatorSpec, NamespacesEventhubOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesEventhubOperatorSpec tests if a specific instance of NamespacesEventhubOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesEventhubOperatorSpec(subject NamespacesEventhubOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesEventhubOperatorSpec + err := copied.AssignProperties_To_NamespacesEventhubOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesEventhubOperatorSpec + err = actual.AssignProperties_From_NamespacesEventhubOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesEventhubOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesEventhubOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesEventhubOperatorSpec, NamespacesEventhubOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesEventhubOperatorSpec runs a test to see if a specific instance of NamespacesEventhubOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesEventhubOperatorSpec(subject NamespacesEventhubOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesEventhubOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesEventhubOperatorSpec instances for property testing - lazily instantiated by +// NamespacesEventhubOperatorSpecGenerator() +var namespacesEventhubOperatorSpecGenerator gopter.Gen + +// NamespacesEventhubOperatorSpecGenerator returns a generator of NamespacesEventhubOperatorSpec instances for property testing. +func NamespacesEventhubOperatorSpecGenerator() gopter.Gen { + if namespacesEventhubOperatorSpecGenerator != nil { + return namespacesEventhubOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesEventhubOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubOperatorSpec{}), generators) + + return namespacesEventhubOperatorSpecGenerator +} + func Test_NamespacesEventhub_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -873,4 +970,5 @@ func AddIndependentPropertyGeneratorsForNamespacesEventhub_Spec(gens map[string] // AddRelatedPropertyGeneratorsForNamespacesEventhub_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesEventhub_Spec(gens map[string]gopter.Gen) { gens["CaptureDescription"] = gen.PtrOf(CaptureDescriptionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesEventhubOperatorSpecGenerator()) } diff --git a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_authorization_rule_types_gen.go b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_authorization_rule_types_gen.go index 6a97293d85c..c4a1181823a 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_authorization_rule_types_gen.go +++ b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_authorization_rule_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (rule *NamespacesEventhubsAuthorizationRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesEventhubsAuthorizationRule resource func (rule *NamespacesEventhubsAuthorizationRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesEventhubsAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesEventhubsAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhubsAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesEventhubsAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesEventhubsAuthorizationRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (rule *NamespacesEventhubsAuthorizationRule) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (rule *NamespacesEventhubsAuthorizationRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,9 +253,20 @@ func (rule *NamespacesEventhubsAuthorizationRule) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return rule.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesEventhubsAuthorizationRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *NamespacesEventhubsAuthorizationRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -253,16 +286,16 @@ func (rule *NamespacesEventhubsAuthorizationRule) validateSecretDestinations() ( if rule.Spec.OperatorSpec == nil { return nil, nil } - if rule.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - rule.Spec.OperatorSpec.Secrets.PrimaryKey, - rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - rule.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if rule.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + rule.Spec.OperatorSpec.Secrets.PrimaryKey, + rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + rule.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(rule, toValidate, rule.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -882,6 +915,12 @@ var namespaces_Eventhubs_AuthorizationRule_Properties_Rights_STATUS_Values = map // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesEventhubsAuthorizationRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespacesEventhubsAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } @@ -889,6 +928,42 @@ type NamespacesEventhubsAuthorizationRuleOperatorSpec struct { // AssignProperties_From_NamespacesEventhubsAuthorizationRuleOperatorSpec populates our NamespacesEventhubsAuthorizationRuleOperatorSpec from the provided source NamespacesEventhubsAuthorizationRuleOperatorSpec func (operator *NamespacesEventhubsAuthorizationRuleOperatorSpec) AssignProperties_From_NamespacesEventhubsAuthorizationRuleOperatorSpec(source *storage.NamespacesEventhubsAuthorizationRuleOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesEventhubsAuthorizationRuleOperatorSecrets @@ -910,6 +985,42 @@ func (operator *NamespacesEventhubsAuthorizationRuleOperatorSpec) AssignProperti // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesEventhubsAuthorizationRuleOperatorSecrets diff --git a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen.go b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen.go index 49c83fd8eef..3dcf6d01df6 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen.go +++ b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *NamespacesEventhubsConsumerGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesEventhubsConsumerGroup resource func (group *NamespacesEventhubsConsumerGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesEventhubsConsumerGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *NamespacesEventhubsConsumerGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhubsConsumerGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *NamespacesEventhubsConsumerGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesEventhubsConsumerGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *NamespacesEventhubsConsumerGroup) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (group *NamespacesEventhubsConsumerGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *NamespacesEventhubsConsumerGroup) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *NamespacesEventhubsConsumerGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *NamespacesEventhubsConsumerGroup) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *NamespacesEventhubsConsumerGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *NamespacesEventhubsConsumerGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesEventhubsConsumerGroup) @@ -332,6 +377,10 @@ type NamespacesEventhubsConsumerGroup_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesEventhubsConsumerGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -382,6 +431,8 @@ func (group *NamespacesEventhubsConsumerGroup_Spec) PopulateFromARM(owner genrun // Set property "AzureName": group.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -457,6 +508,18 @@ func (group *NamespacesEventhubsConsumerGroup_Spec) AssignProperties_From_Namesp // AzureName group.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesEventhubsConsumerGroupOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -480,6 +543,18 @@ func (group *NamespacesEventhubsConsumerGroup_Spec) AssignProperties_To_Namespac // AzureName destination.AzureName = group.AzureName + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.NamespacesEventhubsConsumerGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -784,6 +859,110 @@ func (group *NamespacesEventhubsConsumerGroup_STATUS) AssignProperties_To_Namesp return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesEventhubsConsumerGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec populates our NamespacesEventhubsConsumerGroupOperatorSpec from the provided source NamespacesEventhubsConsumerGroupOperatorSpec +func (operator *NamespacesEventhubsConsumerGroupOperatorSpec) AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec(source *storage.NamespacesEventhubsConsumerGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec populates the provided destination NamespacesEventhubsConsumerGroupOperatorSpec from our NamespacesEventhubsConsumerGroupOperatorSpec +func (operator *NamespacesEventhubsConsumerGroupOperatorSpec) AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec(destination *storage.NamespacesEventhubsConsumerGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesEventhubsConsumerGroup{}, &NamespacesEventhubsConsumerGroupList{}) } diff --git a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen_test.go b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen_test.go index 311f8e6ccce..263077dfcd0 100644 --- a/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen_test.go +++ b/v2/api/eventhub/v1api20211101/namespaces_eventhubs_consumer_group_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup(gens map[st gens["Status"] = NamespacesEventhubsConsumerGroup_STATUSGenerator() } +func Test_NamespacesEventhubsConsumerGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesEventhubsConsumerGroupOperatorSpec to NamespacesEventhubsConsumerGroupOperatorSpec via AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec & AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesEventhubsConsumerGroupOperatorSpec, NamespacesEventhubsConsumerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesEventhubsConsumerGroupOperatorSpec tests if a specific instance of NamespacesEventhubsConsumerGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesEventhubsConsumerGroupOperatorSpec(subject NamespacesEventhubsConsumerGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesEventhubsConsumerGroupOperatorSpec + err := copied.AssignProperties_To_NamespacesEventhubsConsumerGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesEventhubsConsumerGroupOperatorSpec + err = actual.AssignProperties_From_NamespacesEventhubsConsumerGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesEventhubsConsumerGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesEventhubsConsumerGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec, NamespacesEventhubsConsumerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec runs a test to see if a specific instance of NamespacesEventhubsConsumerGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec(subject NamespacesEventhubsConsumerGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesEventhubsConsumerGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesEventhubsConsumerGroupOperatorSpec instances for property testing - lazily instantiated by +// NamespacesEventhubsConsumerGroupOperatorSpecGenerator() +var namespacesEventhubsConsumerGroupOperatorSpecGenerator gopter.Gen + +// NamespacesEventhubsConsumerGroupOperatorSpecGenerator returns a generator of NamespacesEventhubsConsumerGroupOperatorSpec instances for property testing. +func NamespacesEventhubsConsumerGroupOperatorSpecGenerator() gopter.Gen { + if namespacesEventhubsConsumerGroupOperatorSpecGenerator != nil { + return namespacesEventhubsConsumerGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesEventhubsConsumerGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroupOperatorSpec{}), generators) + + return namespacesEventhubsConsumerGroupOperatorSpecGenerator +} + func Test_NamespacesEventhubsConsumerGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -374,6 +471,9 @@ func RunJSONSerializationTestForNamespacesEventhubsConsumerGroup_Spec(subject Na var namespacesEventhubsConsumerGroup_SpecGenerator gopter.Gen // NamespacesEventhubsConsumerGroup_SpecGenerator returns a generator of NamespacesEventhubsConsumerGroup_Spec instances for property testing. +// We first initialize namespacesEventhubsConsumerGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesEventhubsConsumerGroup_SpecGenerator() gopter.Gen { if namespacesEventhubsConsumerGroup_SpecGenerator != nil { return namespacesEventhubsConsumerGroup_SpecGenerator @@ -383,6 +483,12 @@ func NamespacesEventhubsConsumerGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) namespacesEventhubsConsumerGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) + namespacesEventhubsConsumerGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroup_Spec{}), generators) + return namespacesEventhubsConsumerGroup_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(ge gens["AzureName"] = gen.AlphaString() gens["UserMetadata"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesEventhubsConsumerGroupOperatorSpecGenerator()) +} diff --git a/v2/api/eventhub/v1api20211101/storage/namespace_types_gen.go b/v2/api/eventhub/v1api20211101/storage/namespace_types_gen.go index 930ca95b01f..a55cb7638f2 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespace_types_gen.go +++ b/v2/api/eventhub/v1api20211101/storage/namespace_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (namespace *Namespace) SetConditions(conditions conditions.Conditions) { namespace.Status.Conditions = conditions } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -283,8 +306,10 @@ type Identity_STATUS struct { // Storage version of v1api20211101.NamespaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211101.PrivateEndpointConnection_STATUS diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_authorization_rule_types_gen.go b/v2/api/eventhub/v1api20211101/storage/namespaces_authorization_rule_types_gen.go index 48182892d42..a1ddf998278 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_authorization_rule_types_gen.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_authorization_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *NamespacesAuthorizationRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -210,8 +233,10 @@ func (rule *NamespacesAuthorizationRule_STATUS) ConvertStatusTo(destination genr // Storage version of v1api20211101.NamespacesAuthorizationRuleOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211101.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen.go b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen.go index 8524a9748ce..339e5c17a09 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (eventhub *NamespacesEventhub) SetConditions(conditions conditions.Conditio eventhub.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesEventhub{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (eventhub *NamespacesEventhub) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if eventhub.Spec.OperatorSpec == nil { + return nil + } + return eventhub.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhub{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (eventhub *NamespacesEventhub) SecretDestinationExpressions() []*core.DestinationExpression { + if eventhub.Spec.OperatorSpec == nil { + return nil + } + return eventhub.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesEventhub{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type NamespacesEventhubList struct { type NamespacesEventhub_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CaptureDescription *CaptureDescription `json:"captureDescription,omitempty"` - MessageRetentionInDays *int `json:"messageRetentionInDays,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CaptureDescription *CaptureDescription `json:"captureDescription,omitempty"` + MessageRetentionInDays *int `json:"messageRetentionInDays,omitempty"` + OperatorSpec *NamespacesEventhubOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -238,6 +262,14 @@ type CaptureDescription_STATUS struct { SkipEmptyArchives *bool `json:"skipEmptyArchives,omitempty"` } +// Storage version of v1api20211101.NamespacesEventhubOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesEventhubOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.Destination // Capture storage details for capture description type Destination struct { diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen_test.go b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen_test.go index 68bd40e3278..c08c5a92de6 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen_test.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhub_types_gen_test.go @@ -366,6 +366,61 @@ func AddRelatedPropertyGeneratorsForNamespacesEventhub(gens map[string]gopter.Ge gens["Status"] = NamespacesEventhub_STATUSGenerator() } +func Test_NamespacesEventhubOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesEventhubOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesEventhubOperatorSpec, NamespacesEventhubOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesEventhubOperatorSpec runs a test to see if a specific instance of NamespacesEventhubOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesEventhubOperatorSpec(subject NamespacesEventhubOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesEventhubOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesEventhubOperatorSpec instances for property testing - lazily instantiated by +// NamespacesEventhubOperatorSpecGenerator() +var namespacesEventhubOperatorSpecGenerator gopter.Gen + +// NamespacesEventhubOperatorSpecGenerator returns a generator of NamespacesEventhubOperatorSpec instances for property testing. +func NamespacesEventhubOperatorSpecGenerator() gopter.Gen { + if namespacesEventhubOperatorSpecGenerator != nil { + return namespacesEventhubOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesEventhubOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubOperatorSpec{}), generators) + + return namespacesEventhubOperatorSpecGenerator +} + func Test_NamespacesEventhub_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -527,4 +582,5 @@ func AddIndependentPropertyGeneratorsForNamespacesEventhub_Spec(gens map[string] // AddRelatedPropertyGeneratorsForNamespacesEventhub_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesEventhub_Spec(gens map[string]gopter.Gen) { gens["CaptureDescription"] = gen.PtrOf(CaptureDescriptionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesEventhubOperatorSpecGenerator()) } diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_authorization_rule_types_gen.go b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_authorization_rule_types_gen.go index a2bc3dceddd..6d86b7f2c67 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_authorization_rule_types_gen.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_authorization_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *NamespacesEventhubsAuthorizationRule) SetConditions(conditions condi rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesEventhubsAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesEventhubsAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhubsAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesEventhubsAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesEventhubsAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -210,8 +233,10 @@ func (rule *NamespacesEventhubsAuthorizationRule_STATUS) ConvertStatusTo(destina // Storage version of v1api20211101.NamespacesEventhubsAuthorizationRuleOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesEventhubsAuthorizationRuleOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespacesEventhubsAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespacesEventhubsAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211101.NamespacesEventhubsAuthorizationRuleOperatorSecrets diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen.go b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen.go index b71ade1cac2..550efd22fee 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *NamespacesEventhubsConsumerGroup) SetConditions(conditions conditio group.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesEventhubsConsumerGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *NamespacesEventhubsConsumerGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesEventhubsConsumerGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *NamespacesEventhubsConsumerGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesEventhubsConsumerGroup{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type NamespacesEventhubsConsumerGroupList struct { type NamespacesEventhubsConsumerGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *NamespacesEventhubsConsumerGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -208,6 +232,14 @@ func (group *NamespacesEventhubsConsumerGroup_STATUS) ConvertStatusTo(destinatio return destination.ConvertStatusFrom(group) } +// Storage version of v1api20211101.NamespacesEventhubsConsumerGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesEventhubsConsumerGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&NamespacesEventhubsConsumerGroup{}, &NamespacesEventhubsConsumerGroupList{}) } diff --git a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen_test.go b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen_test.go index e50c7f655d8..e1cffddb3ad 100644 --- a/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen_test.go +++ b/v2/api/eventhub/v1api20211101/storage/namespaces_eventhubs_consumer_group_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup(gens map[st gens["Status"] = NamespacesEventhubsConsumerGroup_STATUSGenerator() } +func Test_NamespacesEventhubsConsumerGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesEventhubsConsumerGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec, NamespacesEventhubsConsumerGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec runs a test to see if a specific instance of NamespacesEventhubsConsumerGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesEventhubsConsumerGroupOperatorSpec(subject NamespacesEventhubsConsumerGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesEventhubsConsumerGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesEventhubsConsumerGroupOperatorSpec instances for property testing - lazily instantiated by +// NamespacesEventhubsConsumerGroupOperatorSpecGenerator() +var namespacesEventhubsConsumerGroupOperatorSpecGenerator gopter.Gen + +// NamespacesEventhubsConsumerGroupOperatorSpecGenerator returns a generator of NamespacesEventhubsConsumerGroupOperatorSpec instances for property testing. +func NamespacesEventhubsConsumerGroupOperatorSpecGenerator() gopter.Gen { + if namespacesEventhubsConsumerGroupOperatorSpecGenerator != nil { + return namespacesEventhubsConsumerGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesEventhubsConsumerGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroupOperatorSpec{}), generators) + + return namespacesEventhubsConsumerGroupOperatorSpecGenerator +} + func Test_NamespacesEventhubsConsumerGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -204,6 +259,9 @@ func RunJSONSerializationTestForNamespacesEventhubsConsumerGroup_Spec(subject Na var namespacesEventhubsConsumerGroup_SpecGenerator gopter.Gen // NamespacesEventhubsConsumerGroup_SpecGenerator returns a generator of NamespacesEventhubsConsumerGroup_Spec instances for property testing. +// We first initialize namespacesEventhubsConsumerGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesEventhubsConsumerGroup_SpecGenerator() gopter.Gen { if namespacesEventhubsConsumerGroup_SpecGenerator != nil { return namespacesEventhubsConsumerGroup_SpecGenerator @@ -213,6 +271,12 @@ func NamespacesEventhubsConsumerGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) namespacesEventhubsConsumerGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(generators) + namespacesEventhubsConsumerGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesEventhubsConsumerGroup_Spec{}), generators) + return namespacesEventhubsConsumerGroup_SpecGenerator } @@ -222,3 +286,8 @@ func AddIndependentPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(ge gens["OriginalVersion"] = gen.AlphaString() gens["UserMetadata"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesEventhubsConsumerGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesEventhubsConsumerGroupOperatorSpecGenerator()) +} diff --git a/v2/api/eventhub/v1api20211101/storage/structure.txt b/v2/api/eventhub/v1api20211101/storage/structure.txt index 115e6bf6a93..4ccda0d1105 100644 --- a/v2/api/eventhub/v1api20211101/storage/structure.txt +++ b/v2/api/eventhub/v1api20211101/storage/structure.txt @@ -32,8 +32,10 @@ Namespace: Resource │ ├── KafkaEnabled: *bool │ ├── Location: *string │ ├── MaximumThroughputUnits: *int -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -112,8 +114,10 @@ NamespacesAuthorizationRule: Resource ├── Owner: eventhub/v1api20211101.Namespace ├── Spec: Object (6 properties) │ ├── AzureName: string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -142,7 +146,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesEventhub: Resource ├── Owner: eventhub/v1api20211101.Namespace -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── CaptureDescription: *Object (7 properties) │ │ ├── Destination: *Object (8 properties) @@ -161,6 +165,10 @@ NamespacesEventhub: Resource │ │ ├── SizeLimitInBytes: *int │ │ └── SkipEmptyArchives: *bool │ ├── MessageRetentionInDays: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PartitionCount: *int @@ -206,8 +214,10 @@ NamespacesEventhubsAuthorizationRule: Resource ├── Owner: eventhub/v1api20211101.NamespacesEventhub ├── Spec: Object (6 properties) │ ├── AzureName: string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -236,8 +246,12 @@ NamespacesEventhubsAuthorizationRule: Resource └── Type: *string NamespacesEventhubsConsumerGroup: Resource ├── Owner: eventhub/v1api20211101.NamespacesEventhub -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/eventhub/v1api20211101/storage/zz_generated.deepcopy.go b/v2/api/eventhub/v1api20211101/storage/zz_generated.deepcopy.go index 89d6d35822e..cd56e387a89 100644 --- a/v2/api/eventhub/v1api20211101/storage/zz_generated.deepcopy.go +++ b/v2/api/eventhub/v1api20211101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -577,6 +578,17 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -584,6 +596,17 @@ func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -947,6 +970,17 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -954,6 +988,17 @@ func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesA (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1126,6 +1171,50 @@ func (in *NamespacesEventhubList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesEventhubOperatorSpec) DeepCopyInto(out *NamespacesEventhubOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesEventhubOperatorSpec. +func (in *NamespacesEventhubOperatorSpec) DeepCopy() *NamespacesEventhubOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesEventhubOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhub_STATUS) DeepCopyInto(out *NamespacesEventhub_STATUS) { *out = *in @@ -1228,6 +1317,11 @@ func (in *NamespacesEventhub_Spec) DeepCopyInto(out *NamespacesEventhub_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesEventhubOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1361,6 +1455,17 @@ func (in *NamespacesEventhubsAuthorizationRuleOperatorSecrets) DeepCopy() *Names // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesEventhubsAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -1368,6 +1473,17 @@ func (in *NamespacesEventhubsAuthorizationRuleOperatorSpec) DeepCopyInto(out *Na (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesEventhubsAuthorizationRuleOperatorSecrets) @@ -1540,6 +1656,50 @@ func (in *NamespacesEventhubsConsumerGroupList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesEventhubsConsumerGroupOperatorSpec) DeepCopyInto(out *NamespacesEventhubsConsumerGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesEventhubsConsumerGroupOperatorSpec. +func (in *NamespacesEventhubsConsumerGroupOperatorSpec) DeepCopy() *NamespacesEventhubsConsumerGroupOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesEventhubsConsumerGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsConsumerGroup_STATUS) DeepCopyInto(out *NamespacesEventhubsConsumerGroup_STATUS) { *out = *in @@ -1612,6 +1772,11 @@ func (in *NamespacesEventhubsConsumerGroup_STATUS) DeepCopy() *NamespacesEventhu // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsConsumerGroup_Spec) DeepCopyInto(out *NamespacesEventhubsConsumerGroup_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesEventhubsConsumerGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/eventhub/v1api20211101/structure.txt b/v2/api/eventhub/v1api20211101/structure.txt index 27c59727662..811755f68f3 100644 --- a/v2/api/eventhub/v1api20211101/structure.txt +++ b/v2/api/eventhub/v1api20211101/structure.txt @@ -35,7 +35,9 @@ Namespace: Resource │ ├── KafkaEnabled: *bool │ ├── Location: *string │ ├── MaximumThroughputUnits: *int -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -128,7 +130,9 @@ NamespacesAuthorizationRule: Resource ├── Spec: Object (4 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -166,7 +170,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesEventhub: Resource ├── Owner: Namespace -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 256 │ │ └── Rule 1: MinLength: 1 @@ -189,6 +193,9 @@ NamespacesEventhub: Resource │ │ └── SkipEmptyArchives: *bool │ ├── MessageRetentionInDays: Validated<*int> (1 rule) │ │ └── Rule 0: Minimum: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── PartitionCount: Validated<*int> (1 rule) │ └── Rule 0: Minimum: 1 @@ -249,7 +256,9 @@ NamespacesEventhubsAuthorizationRule: Resource ├── Spec: Object (4 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -287,10 +296,13 @@ NamespacesEventhubsAuthorizationRule: Resource └── Type: *string NamespacesEventhubsConsumerGroup: Resource ├── Owner: NamespacesEventhub -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ └── Rule 1: MinLength: 1 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── UserMetadata: *string └── Status: Object (9 properties) diff --git a/v2/api/eventhub/v1api20211101/zz_generated.deepcopy.go b/v2/api/eventhub/v1api20211101/zz_generated.deepcopy.go index 5ffde892c69..1427fbebe12 100644 --- a/v2/api/eventhub/v1api20211101/zz_generated.deepcopy.go +++ b/v2/api/eventhub/v1api20211101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20211101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -498,6 +499,28 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -840,6 +863,28 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -998,6 +1043,43 @@ func (in *NamespacesEventhubList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesEventhubOperatorSpec) DeepCopyInto(out *NamespacesEventhubOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesEventhubOperatorSpec. +func (in *NamespacesEventhubOperatorSpec) DeepCopy() *NamespacesEventhubOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesEventhubOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhub_STATUS) DeepCopyInto(out *NamespacesEventhub_STATUS) { *out = *in @@ -1093,6 +1175,11 @@ func (in *NamespacesEventhub_Spec) DeepCopyInto(out *NamespacesEventhub_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesEventhubOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1212,6 +1299,28 @@ func (in *NamespacesEventhubsAuthorizationRuleOperatorSecrets) DeepCopy() *Names // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesEventhubsAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesEventhubsAuthorizationRuleOperatorSecrets) @@ -1370,6 +1479,43 @@ func (in *NamespacesEventhubsConsumerGroupList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesEventhubsConsumerGroupOperatorSpec) DeepCopyInto(out *NamespacesEventhubsConsumerGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesEventhubsConsumerGroupOperatorSpec. +func (in *NamespacesEventhubsConsumerGroupOperatorSpec) DeepCopy() *NamespacesEventhubsConsumerGroupOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesEventhubsConsumerGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsConsumerGroup_STATUS) DeepCopyInto(out *NamespacesEventhubsConsumerGroup_STATUS) { *out = *in @@ -1435,6 +1581,11 @@ func (in *NamespacesEventhubsConsumerGroup_STATUS) DeepCopy() *NamespacesEventhu // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesEventhubsConsumerGroup_Spec) DeepCopyInto(out *NamespacesEventhubsConsumerGroup_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesEventhubsConsumerGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20180301/metric_alert_types_gen.go b/v2/api/insights/v1api20180301/metric_alert_types_gen.go index e26cabefb36..331c58c3b5d 100644 --- a/v2/api/insights/v1api20180301/metric_alert_types_gen.go +++ b/v2/api/insights/v1api20180301/metric_alert_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +95,26 @@ func (alert *MetricAlert) defaultAzureName() { // defaultImpl applies the code generated defaults to the MetricAlert resource func (alert *MetricAlert) defaultImpl() { alert.defaultAzureName() } +var _ configmaps.Exporter = &MetricAlert{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (alert *MetricAlert) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if alert.Spec.OperatorSpec == nil { + return nil + } + return alert.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MetricAlert{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (alert *MetricAlert) SecretDestinationExpressions() []*core.DestinationExpression { + if alert.Spec.OperatorSpec == nil { + return nil + } + return alert.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &MetricAlert{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +233,7 @@ func (alert *MetricAlert) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (alert *MetricAlert) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){alert.validateResourceReferences, alert.validateOwnerReference} + return []func() (admission.Warnings, error){alert.validateResourceReferences, alert.validateOwnerReference, alert.validateSecretDestinations, alert.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,7 +251,21 @@ func (alert *MetricAlert) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return alert.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return alert.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return alert.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (alert *MetricAlert) validateConfigMapDestinations() (admission.Warnings, error) { + if alert.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(alert, nil, alert.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -245,6 +282,14 @@ func (alert *MetricAlert) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (alert *MetricAlert) validateSecretDestinations() (admission.Warnings, error) { + if alert.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(alert, nil, alert.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (alert *MetricAlert) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*MetricAlert) @@ -362,6 +407,10 @@ type MetricAlert_Spec struct { // Location: Resource location Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *MetricAlertOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -574,6 +623,8 @@ func (alert *MetricAlert_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe alert.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": alert.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -741,6 +792,18 @@ func (alert *MetricAlert_Spec) AssignProperties_From_MetricAlert_Spec(source *st // Location alert.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec MetricAlertOperatorSpec + err := operatorSpec.AssignProperties_From_MetricAlertOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_MetricAlertOperatorSpec() to populate field OperatorSpec") + } + alert.OperatorSpec = &operatorSpec + } else { + alert.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -844,6 +907,18 @@ func (alert *MetricAlert_Spec) AssignProperties_To_MetricAlert_Spec(destination // Location destination.Location = genruntime.ClonePointerToString(alert.Location) + // OperatorSpec + if alert.OperatorSpec != nil { + var operatorSpec storage.MetricAlertOperatorSpec + err := alert.OperatorSpec.AssignProperties_To_MetricAlertOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_MetricAlertOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = alert.OriginalVersion() @@ -2070,6 +2145,110 @@ func (criteria *MetricAlertCriteria_STATUS) AssignProperties_To_MetricAlertCrite return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MetricAlertOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_MetricAlertOperatorSpec populates our MetricAlertOperatorSpec from the provided source MetricAlertOperatorSpec +func (operator *MetricAlertOperatorSpec) AssignProperties_From_MetricAlertOperatorSpec(source *storage.MetricAlertOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_MetricAlertOperatorSpec populates the provided destination MetricAlertOperatorSpec from our MetricAlertOperatorSpec +func (operator *MetricAlertOperatorSpec) AssignProperties_To_MetricAlertOperatorSpec(destination *storage.MetricAlertOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type MetricAlertMultipleResourceMultipleMetricCriteria struct { AdditionalProperties map[string]v1.JSON `json:"additionalProperties,omitempty"` diff --git a/v2/api/insights/v1api20180301/metric_alert_types_gen_test.go b/v2/api/insights/v1api20180301/metric_alert_types_gen_test.go index d3990667178..cdc8f3225c3 100644 --- a/v2/api/insights/v1api20180301/metric_alert_types_gen_test.go +++ b/v2/api/insights/v1api20180301/metric_alert_types_gen_test.go @@ -1313,6 +1313,103 @@ func AddRelatedPropertyGeneratorsForMetricAlertMultipleResourceMultipleMetricCri gens["AllOf"] = gen.SliceOf(MultiMetricCriteria_STATUSGenerator()) } +func Test_MetricAlertOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from MetricAlertOperatorSpec to MetricAlertOperatorSpec via AssignProperties_To_MetricAlertOperatorSpec & AssignProperties_From_MetricAlertOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForMetricAlertOperatorSpec, MetricAlertOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForMetricAlertOperatorSpec tests if a specific instance of MetricAlertOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForMetricAlertOperatorSpec(subject MetricAlertOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.MetricAlertOperatorSpec + err := copied.AssignProperties_To_MetricAlertOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual MetricAlertOperatorSpec + err = actual.AssignProperties_From_MetricAlertOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_MetricAlertOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MetricAlertOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMetricAlertOperatorSpec, MetricAlertOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMetricAlertOperatorSpec runs a test to see if a specific instance of MetricAlertOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMetricAlertOperatorSpec(subject MetricAlertOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MetricAlertOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MetricAlertOperatorSpec instances for property testing - lazily instantiated by +// MetricAlertOperatorSpecGenerator() +var metricAlertOperatorSpecGenerator gopter.Gen + +// MetricAlertOperatorSpecGenerator returns a generator of MetricAlertOperatorSpec instances for property testing. +func MetricAlertOperatorSpecGenerator() gopter.Gen { + if metricAlertOperatorSpecGenerator != nil { + return metricAlertOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + metricAlertOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MetricAlertOperatorSpec{}), generators) + + return metricAlertOperatorSpecGenerator +} + func Test_MetricAlertSingleResourceMultipleMetricCriteria_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1808,6 +1905,7 @@ func AddIndependentPropertyGeneratorsForMetricAlert_Spec(gens map[string]gopter. func AddRelatedPropertyGeneratorsForMetricAlert_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.SliceOf(MetricAlertActionGenerator()) gens["Criteria"] = gen.PtrOf(MetricAlertCriteriaGenerator()) + gens["OperatorSpec"] = gen.PtrOf(MetricAlertOperatorSpecGenerator()) } func Test_MetricCriteria_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/insights/v1api20180301/storage/metric_alert_types_gen.go b/v2/api/insights/v1api20180301/storage/metric_alert_types_gen.go index 6f24e2791d3..b3005a6756a 100644 --- a/v2/api/insights/v1api20180301/storage/metric_alert_types_gen.go +++ b/v2/api/insights/v1api20180301/storage/metric_alert_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (alert *MetricAlert) SetConditions(conditions conditions.Conditions) { alert.Status.Conditions = conditions } +var _ configmaps.Exporter = &MetricAlert{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (alert *MetricAlert) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if alert.Spec.OperatorSpec == nil { + return nil + } + return alert.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &MetricAlert{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (alert *MetricAlert) SecretDestinationExpressions() []*core.DestinationExpression { + if alert.Spec.OperatorSpec == nil { + return nil + } + return alert.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &MetricAlert{} // AzureName returns the Azure name of the resource @@ -152,13 +175,14 @@ type MetricAlert_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Criteria *MetricAlertCriteria `json:"criteria,omitempty"` - Description *string `json:"description,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - EvaluationFrequency *string `json:"evaluationFrequency,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Criteria *MetricAlertCriteria `json:"criteria,omitempty"` + Description *string `json:"description,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + EvaluationFrequency *string `json:"evaluationFrequency,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *MetricAlertOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -270,6 +294,14 @@ type MetricAlertCriteria_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20180301.MetricAlertOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type MetricAlertOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20180301.MetricAlertMultipleResourceMultipleMetricCriteria type MetricAlertMultipleResourceMultipleMetricCriteria struct { AdditionalProperties map[string]v1.JSON `json:"additionalProperties,omitempty"` diff --git a/v2/api/insights/v1api20180301/storage/metric_alert_types_gen_test.go b/v2/api/insights/v1api20180301/storage/metric_alert_types_gen_test.go index e5ae88d6b57..ed1178fb105 100644 --- a/v2/api/insights/v1api20180301/storage/metric_alert_types_gen_test.go +++ b/v2/api/insights/v1api20180301/storage/metric_alert_types_gen_test.go @@ -797,6 +797,61 @@ func AddRelatedPropertyGeneratorsForMetricAlertMultipleResourceMultipleMetricCri gens["AllOf"] = gen.SliceOf(MultiMetricCriteria_STATUSGenerator()) } +func Test_MetricAlertOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of MetricAlertOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForMetricAlertOperatorSpec, MetricAlertOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForMetricAlertOperatorSpec runs a test to see if a specific instance of MetricAlertOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForMetricAlertOperatorSpec(subject MetricAlertOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual MetricAlertOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of MetricAlertOperatorSpec instances for property testing - lazily instantiated by +// MetricAlertOperatorSpecGenerator() +var metricAlertOperatorSpecGenerator gopter.Gen + +// MetricAlertOperatorSpecGenerator returns a generator of MetricAlertOperatorSpec instances for property testing. +func MetricAlertOperatorSpecGenerator() gopter.Gen { + if metricAlertOperatorSpecGenerator != nil { + return metricAlertOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + metricAlertOperatorSpecGenerator = gen.Struct(reflect.TypeOf(MetricAlertOperatorSpec{}), generators) + + return metricAlertOperatorSpecGenerator +} + func Test_MetricAlertSingleResourceMultipleMetricCriteria_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1125,6 +1180,7 @@ func AddIndependentPropertyGeneratorsForMetricAlert_Spec(gens map[string]gopter. func AddRelatedPropertyGeneratorsForMetricAlert_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.SliceOf(MetricAlertActionGenerator()) gens["Criteria"] = gen.PtrOf(MetricAlertCriteriaGenerator()) + gens["OperatorSpec"] = gen.PtrOf(MetricAlertOperatorSpecGenerator()) } func Test_MetricCriteria_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/insights/v1api20180301/storage/structure.txt b/v2/api/insights/v1api20180301/storage/structure.txt index a41db45a43b..b8342bfdfa1 100644 --- a/v2/api/insights/v1api20180301/storage/structure.txt +++ b/v2/api/insights/v1api20180301/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-03-01" MetricAlert: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── Actions: Object (3 properties)[] │ │ ├── ActionGroupId: *string │ │ ├── PropertyBag: genruntime.PropertyBag @@ -88,6 +88,10 @@ MetricAlert: Resource │ ├── Enabled: *bool │ ├── EvaluationFrequency: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/insights/v1api20180301/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20180301/storage/zz_generated.deepcopy.go index 30df3918ce5..b404864515f 100644 --- a/v2/api/insights/v1api20180301/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20180301/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -535,6 +536,50 @@ func (in *MetricAlertMultipleResourceMultipleMetricCriteria_STATUS) DeepCopy() * return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetricAlertOperatorSpec) DeepCopyInto(out *MetricAlertOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricAlertOperatorSpec. +func (in *MetricAlertOperatorSpec) DeepCopy() *MetricAlertOperatorSpec { + if in == nil { + return nil + } + out := new(MetricAlertOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricAlertSingleResourceMultipleMetricCriteria) DeepCopyInto(out *MetricAlertSingleResourceMultipleMetricCriteria) { *out = *in @@ -780,6 +825,11 @@ func (in *MetricAlert_Spec) DeepCopyInto(out *MetricAlert_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MetricAlertOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20180301/structure.txt b/v2/api/insights/v1api20180301/structure.txt index 5a4987c4046..532932d03d9 100644 --- a/v2/api/insights/v1api20180301/structure.txt +++ b/v2/api/insights/v1api20180301/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-03-01" MetricAlert: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── Actions: Object (2 properties)[] │ │ ├── ActionGroupId: *string │ │ └── WebHookProperties: map[string]string @@ -112,6 +112,9 @@ MetricAlert: Resource │ ├── Enabled: *bool │ ├── EvaluationFrequency: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ScopesReferences: genruntime.ResourceReference[] │ ├── Severity: *int diff --git a/v2/api/insights/v1api20180301/zz_generated.deepcopy.go b/v2/api/insights/v1api20180301/zz_generated.deepcopy.go index 95887438a0c..57da51ef7d7 100644 --- a/v2/api/insights/v1api20180301/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20180301/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180301 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -465,6 +466,43 @@ func (in *MetricAlertMultipleResourceMultipleMetricCriteria_STATUS) DeepCopy() * return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetricAlertOperatorSpec) DeepCopyInto(out *MetricAlertOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricAlertOperatorSpec. +func (in *MetricAlertOperatorSpec) DeepCopy() *MetricAlertOperatorSpec { + if in == nil { + return nil + } + out := new(MetricAlertOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetricAlertSingleResourceMultipleMetricCriteria) DeepCopyInto(out *MetricAlertSingleResourceMultipleMetricCriteria) { *out = *in @@ -689,6 +727,11 @@ func (in *MetricAlert_Spec) DeepCopyInto(out *MetricAlert_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(MetricAlertOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20180501preview/storage/structure.txt b/v2/api/insights/v1api20180501preview/storage/structure.txt index 0381280cf41..e6f2fd1ed6d 100644 --- a/v2/api/insights/v1api20180501preview/storage/structure.txt +++ b/v2/api/insights/v1api20180501preview/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-05-01-preview" Webtest: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AzureName: string │ ├── Configuration: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -19,6 +19,10 @@ Webtest: Resource │ │ ├── Id: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Name: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -106,5 +110,6 @@ augmentConversionForWebTestProperties_ValidationRules_ContentValidation: Interfa augmentConversionForWebTestProperties_ValidationRules_ContentValidation_STATUS: Interface augmentConversionForWebTestProperties_ValidationRules_STATUS: Interface augmentConversionForWebtest: Interface +augmentConversionForWebtestOperatorSpec: Interface augmentConversionForWebtest_STATUS: Interface augmentConversionForWebtest_Spec: Interface diff --git a/v2/api/insights/v1api20180501preview/storage/webtest_types_gen.go b/v2/api/insights/v1api20180501preview/storage/webtest_types_gen.go index 17dcbb578ac..6e708882200 100644 --- a/v2/api/insights/v1api20180501preview/storage/webtest_types_gen.go +++ b/v2/api/insights/v1api20180501preview/storage/webtest_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/insights/v1api20220615/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (webtest *Webtest) ConvertTo(hub conversion.Hub) error { return webtest.AssignProperties_To_Webtest(destination) } +var _ configmaps.Exporter = &Webtest{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (webtest *Webtest) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Webtest{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (webtest *Webtest) SecretDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Webtest{} // AzureName returns the Azure name of the resource @@ -250,6 +273,7 @@ type Webtest_Spec struct { Location *string `json:"location,omitempty"` Locations []WebTestGeolocation `json:"Locations,omitempty"` Name *string `json:"Name,omitempty"` + OperatorSpec *WebtestOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -377,6 +401,18 @@ func (webtest *Webtest_Spec) AssignProperties_From_Webtest_Spec(source *storage. // Name webtest.Name = genruntime.ClonePointerToString(source.Name) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WebtestOperatorSpec + err := operatorSpec.AssignProperties_From_WebtestOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WebtestOperatorSpec() to populate field OperatorSpec") + } + webtest.OperatorSpec = &operatorSpec + } else { + webtest.OperatorSpec = nil + } + // OriginalVersion webtest.OriginalVersion = source.OriginalVersion @@ -510,6 +546,18 @@ func (webtest *Webtest_Spec) AssignProperties_To_Webtest_Spec(destination *stora // Name destination.Name = genruntime.ClonePointerToString(webtest.Name) + // OperatorSpec + if webtest.OperatorSpec != nil { + var operatorSpec storage.WebtestOperatorSpec + err := webtest.OperatorSpec.AssignProperties_To_WebtestOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WebtestOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = webtest.OriginalVersion @@ -1060,6 +1108,136 @@ func (geolocation *WebTestGeolocation_STATUS) AssignProperties_To_WebTestGeoloca return nil } +// Storage version of v1api20180501preview.WebtestOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebtestOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WebtestOperatorSpec populates our WebtestOperatorSpec from the provided source WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_From_WebtestOperatorSpec(source *storage.WebtestOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForWebtestOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWebtestOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_WebtestOperatorSpec populates the provided destination WebtestOperatorSpec from our WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_To_WebtestOperatorSpec(destination *storage.WebtestOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForWebtestOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWebtestOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20180501preview.WebTestProperties_Configuration type WebTestProperties_Configuration struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` @@ -1792,6 +1970,11 @@ type augmentConversionForWebTestGeolocation_STATUS interface { AssignPropertiesTo(dst *storage.WebTestGeolocation_STATUS) error } +type augmentConversionForWebtestOperatorSpec interface { + AssignPropertiesFrom(src *storage.WebtestOperatorSpec) error + AssignPropertiesTo(dst *storage.WebtestOperatorSpec) error +} + type augmentConversionForWebTestProperties_Configuration interface { AssignPropertiesFrom(src *storage.WebTestProperties_Configuration) error AssignPropertiesTo(dst *storage.WebTestProperties_Configuration) error diff --git a/v2/api/insights/v1api20180501preview/storage/webtest_types_gen_test.go b/v2/api/insights/v1api20180501preview/storage/webtest_types_gen_test.go index 148d098f88d..2658fb871dd 100644 --- a/v2/api/insights/v1api20180501preview/storage/webtest_types_gen_test.go +++ b/v2/api/insights/v1api20180501preview/storage/webtest_types_gen_test.go @@ -1473,6 +1473,103 @@ func AddRelatedPropertyGeneratorsForWebtest(gens map[string]gopter.Gen) { gens["Status"] = Webtest_STATUSGenerator() } +func Test_WebtestOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WebtestOperatorSpec to WebtestOperatorSpec via AssignProperties_To_WebtestOperatorSpec & AssignProperties_From_WebtestOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWebtestOperatorSpec tests if a specific instance of WebtestOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WebtestOperatorSpec + err := copied.AssignProperties_To_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WebtestOperatorSpec + err = actual.AssignProperties_From_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WebtestOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebtestOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebtestOperatorSpec runs a test to see if a specific instance of WebtestOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebtestOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebtestOperatorSpec instances for property testing - lazily instantiated by +// WebtestOperatorSpecGenerator() +var webtestOperatorSpecGenerator gopter.Gen + +// WebtestOperatorSpecGenerator returns a generator of WebtestOperatorSpec instances for property testing. +func WebtestOperatorSpecGenerator() gopter.Gen { + if webtestOperatorSpecGenerator != nil { + return webtestOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webtestOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebtestOperatorSpec{}), generators) + + return webtestOperatorSpecGenerator +} + func Test_Webtest_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1735,6 +1832,7 @@ func AddIndependentPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) { gens["Configuration"] = gen.PtrOf(WebTestProperties_ConfigurationGenerator()) gens["Locations"] = gen.SliceOf(WebTestGeolocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebtestOperatorSpecGenerator()) gens["Request"] = gen.PtrOf(WebTestProperties_RequestGenerator()) gens["ValidationRules"] = gen.PtrOf(WebTestProperties_ValidationRulesGenerator()) } diff --git a/v2/api/insights/v1api20180501preview/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20180501preview/storage/zz_generated.deepcopy.go index 9f82687120d..644611b6841 100644 --- a/v2/api/insights/v1api20180501preview/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20180501preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -522,6 +523,50 @@ func (in *WebtestList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebtestOperatorSpec) DeepCopyInto(out *WebtestOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebtestOperatorSpec. +func (in *WebtestOperatorSpec) DeepCopy() *WebtestOperatorSpec { + if in == nil { + return nil + } + out := new(WebtestOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webtest_STATUS) DeepCopyInto(out *Webtest_STATUS) { *out = *in @@ -690,6 +735,11 @@ func (in *Webtest_Spec) DeepCopyInto(out *Webtest_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebtestOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20180501preview/structure.txt b/v2/api/insights/v1api20180501preview/structure.txt index 18b06a09455..f9b66d750bb 100644 --- a/v2/api/insights/v1api20180501preview/structure.txt +++ b/v2/api/insights/v1api20180501preview/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2018-05-01-preview" Webtest: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AzureName: string │ ├── Configuration: *Object (1 property) │ │ └── WebTest: *string @@ -21,6 +21,9 @@ Webtest: Resource │ ├── Locations: Object (1 property)[] │ │ └── Id: *string │ ├── Name: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Request: *Object (6 properties) │ │ ├── FollowRedirects: *bool diff --git a/v2/api/insights/v1api20180501preview/webtest_types_gen.go b/v2/api/insights/v1api20180501preview/webtest_types_gen.go index 9ac9bdd7f4d..6f4fe35eab2 100644 --- a/v2/api/insights/v1api20180501preview/webtest_types_gen.go +++ b/v2/api/insights/v1api20180501preview/webtest_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (webtest *Webtest) defaultAzureName() { // defaultImpl applies the code generated defaults to the Webtest resource func (webtest *Webtest) defaultImpl() { webtest.defaultAzureName() } +var _ configmaps.Exporter = &Webtest{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (webtest *Webtest) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Webtest{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (webtest *Webtest) SecretDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Webtest{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (webtest *Webtest) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (webtest *Webtest) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){webtest.validateResourceReferences, webtest.validateOwnerReference} + return []func() (admission.Warnings, error){webtest.validateResourceReferences, webtest.validateOwnerReference, webtest.validateSecretDestinations, webtest.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (webtest *Webtest) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return webtest.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return webtest.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return webtest.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (webtest *Webtest) validateConfigMapDestinations() (admission.Warnings, error) { + if webtest.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(webtest, nil, webtest.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (webtest *Webtest) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (webtest *Webtest) validateSecretDestinations() (admission.Warnings, error) { + if webtest.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(webtest, nil, webtest.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (webtest *Webtest) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Webtest) @@ -367,6 +412,10 @@ type Webtest_Spec struct { // Name: User defined name if this WebTest. Name *string `json:"Name,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WebtestOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -597,6 +646,8 @@ func (webtest *Webtest_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": webtest.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -785,6 +836,18 @@ func (webtest *Webtest_Spec) AssignProperties_From_Webtest_Spec(source *storage. // Name webtest.Name = genruntime.ClonePointerToString(source.Name) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WebtestOperatorSpec + err := operatorSpec.AssignProperties_From_WebtestOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WebtestOperatorSpec() to populate field OperatorSpec") + } + webtest.OperatorSpec = &operatorSpec + } else { + webtest.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -904,6 +967,18 @@ func (webtest *Webtest_Spec) AssignProperties_To_Webtest_Spec(destination *stora // Name destination.Name = genruntime.ClonePointerToString(webtest.Name) + // OperatorSpec + if webtest.OperatorSpec != nil { + var operatorSpec storage.WebtestOperatorSpec + err := webtest.OperatorSpec.AssignProperties_To_WebtestOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WebtestOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = webtest.OriginalVersion() @@ -1662,6 +1737,110 @@ func (geolocation *WebTestGeolocation_STATUS) AssignProperties_To_WebTestGeoloca return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebtestOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WebtestOperatorSpec populates our WebtestOperatorSpec from the provided source WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_From_WebtestOperatorSpec(source *storage.WebtestOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WebtestOperatorSpec populates the provided destination WebtestOperatorSpec from our WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_To_WebtestOperatorSpec(destination *storage.WebtestOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type WebTestProperties_Configuration struct { // WebTest: The XML specification of a WebTest to run against an application. WebTest *string `json:"WebTest,omitempty"` diff --git a/v2/api/insights/v1api20180501preview/webtest_types_gen_test.go b/v2/api/insights/v1api20180501preview/webtest_types_gen_test.go index 455abedea8b..3a08bd933b7 100644 --- a/v2/api/insights/v1api20180501preview/webtest_types_gen_test.go +++ b/v2/api/insights/v1api20180501preview/webtest_types_gen_test.go @@ -1474,6 +1474,103 @@ func AddRelatedPropertyGeneratorsForWebtest(gens map[string]gopter.Gen) { gens["Status"] = Webtest_STATUSGenerator() } +func Test_WebtestOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WebtestOperatorSpec to WebtestOperatorSpec via AssignProperties_To_WebtestOperatorSpec & AssignProperties_From_WebtestOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWebtestOperatorSpec tests if a specific instance of WebtestOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20180501ps.WebtestOperatorSpec + err := copied.AssignProperties_To_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WebtestOperatorSpec + err = actual.AssignProperties_From_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WebtestOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebtestOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebtestOperatorSpec runs a test to see if a specific instance of WebtestOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebtestOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebtestOperatorSpec instances for property testing - lazily instantiated by +// WebtestOperatorSpecGenerator() +var webtestOperatorSpecGenerator gopter.Gen + +// WebtestOperatorSpecGenerator returns a generator of WebtestOperatorSpec instances for property testing. +func WebtestOperatorSpecGenerator() gopter.Gen { + if webtestOperatorSpecGenerator != nil { + return webtestOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webtestOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebtestOperatorSpec{}), generators) + + return webtestOperatorSpecGenerator +} + func Test_Webtest_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1743,6 +1840,7 @@ func AddIndependentPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) { gens["Configuration"] = gen.PtrOf(WebTestProperties_ConfigurationGenerator()) gens["Locations"] = gen.SliceOf(WebTestGeolocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebtestOperatorSpecGenerator()) gens["Request"] = gen.PtrOf(WebTestProperties_RequestGenerator()) gens["ValidationRules"] = gen.PtrOf(WebTestProperties_ValidationRulesGenerator()) } diff --git a/v2/api/insights/v1api20180501preview/zz_generated.deepcopy.go b/v2/api/insights/v1api20180501preview/zz_generated.deepcopy.go index 95a6f9f1107..58697402e9d 100644 --- a/v2/api/insights/v1api20180501preview/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20180501preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180501preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -438,6 +439,43 @@ func (in *WebtestList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebtestOperatorSpec) DeepCopyInto(out *WebtestOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebtestOperatorSpec. +func (in *WebtestOperatorSpec) DeepCopy() *WebtestOperatorSpec { + if in == nil { + return nil + } + out := new(WebtestOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webtest_STATUS) DeepCopyInto(out *Webtest_STATUS) { *out = *in @@ -599,6 +637,11 @@ func (in *Webtest_Spec) DeepCopyInto(out *Webtest_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebtestOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20200202/component_types_gen.go b/v2/api/insights/v1api20200202/component_types_gen.go index 35687903493..c6a78e02fce 100644 --- a/v2/api/insights/v1api20200202/component_types_gen.go +++ b/v2/api/insights/v1api20200202/component_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (component *Component) defaultAzureName() { // defaultImpl applies the code generated defaults to the Component resource func (component *Component) defaultImpl() { component.defaultAzureName() } +var _ configmaps.Exporter = &Component{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (component *Component) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if component.Spec.OperatorSpec == nil { + return nil + } + return component.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Component{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (component *Component) SecretDestinationExpressions() []*core.DestinationExpression { + if component.Spec.OperatorSpec == nil { + return nil + } + return component.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Component{} // InitializeSpec initializes the spec for this resource from the given status @@ -236,7 +258,7 @@ func (component *Component) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (component *Component) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){component.validateResourceReferences, component.validateOwnerReference, component.validateConfigMapDestinations} + return []func() (admission.Warnings, error){component.validateResourceReferences, component.validateOwnerReference, component.validateSecretDestinations, component.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -254,6 +276,9 @@ func (component *Component) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return component.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return component.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return component.validateConfigMapDestinations() }, @@ -265,14 +290,14 @@ func (component *Component) validateConfigMapDestinations() (admission.Warnings, if component.Spec.OperatorSpec == nil { return nil, nil } - if component.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - component.Spec.OperatorSpec.ConfigMaps.ConnectionString, - component.Spec.OperatorSpec.ConfigMaps.InstrumentationKey, + var toValidate []*genruntime.ConfigMapDestination + if component.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + component.Spec.OperatorSpec.ConfigMaps.ConnectionString, + component.Spec.OperatorSpec.ConfigMaps.InstrumentationKey, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(component, toValidate, component.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -289,6 +314,14 @@ func (component *Component) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (component *Component) validateSecretDestinations() (admission.Warnings, error) { + if component.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(component, nil, component.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (component *Component) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Component) @@ -2184,13 +2217,37 @@ var applicationInsightsComponentProperties_Request_Source_STATUS_Values = map[st // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ComponentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ComponentOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_ComponentOperatorSpec populates our ComponentOperatorSpec from the provided source ComponentOperatorSpec func (operator *ComponentOperatorSpec) AssignProperties_From_ComponentOperatorSpec(source *storage.ComponentOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ComponentOperatorConfigMaps @@ -2203,6 +2260,24 @@ func (operator *ComponentOperatorSpec) AssignProperties_From_ComponentOperatorSp operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2212,6 +2287,24 @@ func (operator *ComponentOperatorSpec) AssignProperties_To_ComponentOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ComponentOperatorConfigMaps @@ -2224,6 +2317,24 @@ func (operator *ComponentOperatorSpec) AssignProperties_To_ComponentOperatorSpec destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/insights/v1api20200202/storage/component_types_gen.go b/v2/api/insights/v1api20200202/storage/component_types_gen.go index b2e5e2b9332..015cb2fafcc 100644 --- a/v2/api/insights/v1api20200202/storage/component_types_gen.go +++ b/v2/api/insights/v1api20200202/storage/component_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (component *Component) SetConditions(conditions conditions.Conditions) { component.Status.Conditions = conditions } +var _ configmaps.Exporter = &Component{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (component *Component) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if component.Spec.OperatorSpec == nil { + return nil + } + return component.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Component{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (component *Component) SecretDestinationExpressions() []*core.DestinationExpression { + if component.Spec.OperatorSpec == nil { + return nil + } + return component.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Component{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -290,8 +312,10 @@ func (component *Component_STATUS) ConvertStatusTo(destination genruntime.Conver // Storage version of v1api20200202.ComponentOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ComponentOperatorSpec struct { - ConfigMaps *ComponentOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ComponentOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20200202.PrivateLinkScopedResource_STATUS diff --git a/v2/api/insights/v1api20200202/storage/structure.txt b/v2/api/insights/v1api20200202/storage/structure.txt index d140e6a27d8..3363b723db4 100644 --- a/v2/api/insights/v1api20200202/storage/structure.txt +++ b/v2/api/insights/v1api20200202/storage/structure.txt @@ -18,12 +18,14 @@ Component: Resource │ ├── IngestionMode: *string │ ├── Kind: *string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── ConnectionString: *genruntime.ConfigMapDestination │ │ │ ├── InstrumentationKey: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/insights/v1api20200202/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20200202/storage/zz_generated.deepcopy.go index 762bfed4878..69712c156d0 100644 --- a/v2/api/insights/v1api20200202/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20200202/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -109,6 +110,17 @@ func (in *ComponentOperatorConfigMaps) DeepCopy() *ComponentOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentOperatorSpec) DeepCopyInto(out *ComponentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ComponentOperatorConfigMaps) @@ -121,6 +133,17 @@ func (in *ComponentOperatorSpec) DeepCopyInto(out *ComponentOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentOperatorSpec. diff --git a/v2/api/insights/v1api20200202/structure.txt b/v2/api/insights/v1api20200202/structure.txt index aef4846ab8a..2fe7ca4d1b2 100644 --- a/v2/api/insights/v1api20200202/structure.txt +++ b/v2/api/insights/v1api20200202/structure.txt @@ -24,10 +24,12 @@ Component: Resource │ │ └── "LogAnalytics" │ ├── Kind: *string │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (2 properties) -│ │ ├── ConnectionString: *genruntime.ConfigMapDestination -│ │ └── InstrumentationKey: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (2 properties) +│ │ │ ├── ConnectionString: *genruntime.ConfigMapDestination +│ │ │ └── InstrumentationKey: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccessForIngestion: *Enum (2 values) │ │ ├── "Disabled" diff --git a/v2/api/insights/v1api20200202/zz_generated.deepcopy.go b/v2/api/insights/v1api20200202/zz_generated.deepcopy.go index 810560c1863..301a11d87e5 100644 --- a/v2/api/insights/v1api20200202/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20200202/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20200202 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -102,11 +103,33 @@ func (in *ComponentOperatorConfigMaps) DeepCopy() *ComponentOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ComponentOperatorSpec) DeepCopyInto(out *ComponentOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ComponentOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentOperatorSpec. diff --git a/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen.go b/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen.go index 35efc99220c..2021be8e949 100644 --- a/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen.go +++ b/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (setting *DiagnosticSetting) defaultAzureName() { // defaultImpl applies the code generated defaults to the DiagnosticSetting resource func (setting *DiagnosticSetting) defaultImpl() { setting.defaultAzureName() } +var _ configmaps.Exporter = &DiagnosticSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *DiagnosticSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiagnosticSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *DiagnosticSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DiagnosticSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (setting *DiagnosticSetting) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (setting *DiagnosticSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,22 @@ func (setting *DiagnosticSetting) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return setting.validateResourceReferences() }, - setting.validateWriteOnceProperties} + setting.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *DiagnosticSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -234,6 +272,14 @@ func (setting *DiagnosticSetting) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *DiagnosticSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *DiagnosticSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DiagnosticSetting) @@ -346,6 +392,10 @@ type DiagnosticSetting_Spec struct { // Metrics: The list of metric settings. Metrics []MetricSettings `json:"metrics,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DiagnosticSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. This resource is an @@ -512,6 +562,8 @@ func (setting *DiagnosticSetting_Spec) PopulateFromARM(owner genruntime.Arbitrar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &owner @@ -646,6 +698,18 @@ func (setting *DiagnosticSetting_Spec) AssignProperties_From_DiagnosticSetting_S setting.Metrics = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DiagnosticSettingOperatorSpec + err := operatorSpec.AssignProperties_From_DiagnosticSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DiagnosticSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -743,6 +807,18 @@ func (setting *DiagnosticSetting_Spec) AssignProperties_To_DiagnosticSetting_Spe destination.Metrics = nil } + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.DiagnosticSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_DiagnosticSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DiagnosticSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -1299,6 +1375,110 @@ func (setting *DiagnosticSetting_STATUS) AssignProperties_To_DiagnosticSetting_S return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiagnosticSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DiagnosticSettingOperatorSpec populates our DiagnosticSettingOperatorSpec from the provided source DiagnosticSettingOperatorSpec +func (operator *DiagnosticSettingOperatorSpec) AssignProperties_From_DiagnosticSettingOperatorSpec(source *storage.DiagnosticSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DiagnosticSettingOperatorSpec populates the provided destination DiagnosticSettingOperatorSpec from our DiagnosticSettingOperatorSpec +func (operator *DiagnosticSettingOperatorSpec) AssignProperties_To_DiagnosticSettingOperatorSpec(destination *storage.DiagnosticSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Part of MultiTenantDiagnosticSettings. Specifies the settings for a particular log. type LogSettings struct { // Category: Name of a Diagnostic Log category for a resource type this setting is applied to. To obtain the list of diff --git a/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen_test.go b/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen_test.go index ec71a5d8868..f5b6aef3ee8 100644 --- a/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen_test.go +++ b/v2/api/insights/v1api20210501preview/diagnostic_setting_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDiagnosticSetting(gens map[string]gopter.Gen gens["Status"] = DiagnosticSetting_STATUSGenerator() } +func Test_DiagnosticSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DiagnosticSettingOperatorSpec to DiagnosticSettingOperatorSpec via AssignProperties_To_DiagnosticSettingOperatorSpec & AssignProperties_From_DiagnosticSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDiagnosticSettingOperatorSpec, DiagnosticSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDiagnosticSettingOperatorSpec tests if a specific instance of DiagnosticSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDiagnosticSettingOperatorSpec(subject DiagnosticSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DiagnosticSettingOperatorSpec + err := copied.AssignProperties_To_DiagnosticSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DiagnosticSettingOperatorSpec + err = actual.AssignProperties_From_DiagnosticSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DiagnosticSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiagnosticSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiagnosticSettingOperatorSpec, DiagnosticSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiagnosticSettingOperatorSpec runs a test to see if a specific instance of DiagnosticSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiagnosticSettingOperatorSpec(subject DiagnosticSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiagnosticSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiagnosticSettingOperatorSpec instances for property testing - lazily instantiated by +// DiagnosticSettingOperatorSpecGenerator() +var diagnosticSettingOperatorSpecGenerator gopter.Gen + +// DiagnosticSettingOperatorSpecGenerator returns a generator of DiagnosticSettingOperatorSpec instances for property testing. +func DiagnosticSettingOperatorSpecGenerator() gopter.Gen { + if diagnosticSettingOperatorSpecGenerator != nil { + return diagnosticSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diagnosticSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiagnosticSettingOperatorSpec{}), generators) + + return diagnosticSettingOperatorSpecGenerator +} + func Test_DiagnosticSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -411,6 +508,7 @@ func AddIndependentPropertyGeneratorsForDiagnosticSetting_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiagnosticSetting_Spec(gens map[string]gopter.Gen) { gens["Logs"] = gen.SliceOf(LogSettingsGenerator()) gens["Metrics"] = gen.SliceOf(MetricSettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiagnosticSettingOperatorSpecGenerator()) } func Test_LogSettings_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen.go b/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen.go index e76031e7942..0c7a935217f 100644 --- a/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen.go +++ b/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/insights/v1api20220615/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (setting *DiagnosticSetting) SetConditions(conditions conditions.Conditions setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &DiagnosticSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *DiagnosticSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DiagnosticSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *DiagnosticSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DiagnosticSetting{} // AzureName returns the Azure name of the resource @@ -158,9 +181,10 @@ type DiagnosticSetting_Spec struct { // MarketplacePartnerReference: The full ARM resource ID of the Marketplace resource to which you would like to send // Diagnostic Logs. - MarketplacePartnerReference *genruntime.ResourceReference `armReference:"MarketplacePartnerId" json:"marketplacePartnerReference,omitempty"` - Metrics []MetricSettings `json:"metrics,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + MarketplacePartnerReference *genruntime.ResourceReference `armReference:"MarketplacePartnerId" json:"marketplacePartnerReference,omitempty"` + Metrics []MetricSettings `json:"metrics,omitempty"` + OperatorSpec *DiagnosticSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -238,6 +262,14 @@ func (setting *DiagnosticSetting_STATUS) ConvertStatusTo(destination genruntime. return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20210501preview.DiagnosticSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DiagnosticSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210501preview.LogSettings // Part of MultiTenantDiagnosticSettings. Specifies the settings for a particular log. type LogSettings struct { diff --git a/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen_test.go b/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen_test.go index a65d19fdff3..38333bf7684 100644 --- a/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen_test.go +++ b/v2/api/insights/v1api20210501preview/storage/diagnostic_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDiagnosticSetting(gens map[string]gopter.Gen gens["Status"] = DiagnosticSetting_STATUSGenerator() } +func Test_DiagnosticSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DiagnosticSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDiagnosticSettingOperatorSpec, DiagnosticSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDiagnosticSettingOperatorSpec runs a test to see if a specific instance of DiagnosticSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDiagnosticSettingOperatorSpec(subject DiagnosticSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DiagnosticSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DiagnosticSettingOperatorSpec instances for property testing - lazily instantiated by +// DiagnosticSettingOperatorSpecGenerator() +var diagnosticSettingOperatorSpecGenerator gopter.Gen + +// DiagnosticSettingOperatorSpecGenerator returns a generator of DiagnosticSettingOperatorSpec instances for property testing. +func DiagnosticSettingOperatorSpecGenerator() gopter.Gen { + if diagnosticSettingOperatorSpecGenerator != nil { + return diagnosticSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + diagnosticSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DiagnosticSettingOperatorSpec{}), generators) + + return diagnosticSettingOperatorSpecGenerator +} + func Test_DiagnosticSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -243,6 +298,7 @@ func AddIndependentPropertyGeneratorsForDiagnosticSetting_Spec(gens map[string]g func AddRelatedPropertyGeneratorsForDiagnosticSetting_Spec(gens map[string]gopter.Gen) { gens["Logs"] = gen.SliceOf(LogSettingsGenerator()) gens["Metrics"] = gen.SliceOf(MetricSettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DiagnosticSettingOperatorSpecGenerator()) } func Test_LogSettings_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/insights/v1api20210501preview/storage/structure.txt b/v2/api/insights/v1api20210501preview/storage/structure.txt index 0d03137c9b5..c1d2109be95 100644 --- a/v2/api/insights/v1api20210501preview/storage/structure.txt +++ b/v2/api/insights/v1api20210501preview/storage/structure.txt @@ -4,7 +4,7 @@ github.com/Azure/azure-service-operator/v2/api/insights/v1api20210501preview/sto APIVersion: Enum (1 value) └── "2021-05-01-preview" DiagnosticSetting: Resource -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── EventHubAuthorizationRuleReference: *genruntime.ResourceReference │ ├── EventHubName: *string @@ -28,6 +28,10 @@ DiagnosticSetting: Resource │ │ │ ├── Enabled: *bool │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── TimeGrain: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/insights/v1api20210501preview/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20210501preview/storage/zz_generated.deepcopy.go index 9a9be4886a3..16793077bdd 100644 --- a/v2/api/insights/v1api20210501preview/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20210501preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *DiagnosticSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiagnosticSettingOperatorSpec) DeepCopyInto(out *DiagnosticSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiagnosticSettingOperatorSpec. +func (in *DiagnosticSettingOperatorSpec) DeepCopy() *DiagnosticSettingOperatorSpec { + if in == nil { + return nil + } + out := new(DiagnosticSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiagnosticSetting_STATUS) DeepCopyInto(out *DiagnosticSetting_STATUS) { *out = *in @@ -209,6 +254,11 @@ func (in *DiagnosticSetting_Spec) DeepCopyInto(out *DiagnosticSetting_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiagnosticSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) diff --git a/v2/api/insights/v1api20210501preview/structure.txt b/v2/api/insights/v1api20210501preview/structure.txt index 26ad78c6770..46a8af74eeb 100644 --- a/v2/api/insights/v1api20210501preview/structure.txt +++ b/v2/api/insights/v1api20210501preview/structure.txt @@ -4,7 +4,7 @@ github.com/Azure/azure-service-operator/v2/api/insights/v1api20210501preview APIVersion: Enum (1 value) └── "2021-05-01-preview" DiagnosticSetting: Resource -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── EventHubAuthorizationRuleReference: *genruntime.ResourceReference │ ├── EventHubName: *string @@ -26,6 +26,9 @@ DiagnosticSetting: Resource │ │ │ │ └── Rule 0: Minimum: 0 │ │ │ └── Enabled: *bool │ │ └── TimeGrain: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── ServiceBusRuleId: *string │ ├── StorageAccountReference: *genruntime.ResourceReference diff --git a/v2/api/insights/v1api20210501preview/zz_generated.deepcopy.go b/v2/api/insights/v1api20210501preview/zz_generated.deepcopy.go index eca9f2304b8..41b1dc4581c 100644 --- a/v2/api/insights/v1api20210501preview/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20210501preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210501preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *DiagnosticSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiagnosticSettingOperatorSpec) DeepCopyInto(out *DiagnosticSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiagnosticSettingOperatorSpec. +func (in *DiagnosticSettingOperatorSpec) DeepCopy() *DiagnosticSettingOperatorSpec { + if in == nil { + return nil + } + out := new(DiagnosticSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiagnosticSetting_STATUS) DeepCopyInto(out *DiagnosticSetting_STATUS) { *out = *in @@ -202,6 +240,11 @@ func (in *DiagnosticSetting_Spec) DeepCopyInto(out *DiagnosticSetting_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DiagnosticSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) diff --git a/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen.go b/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen.go index ff9e2ccd09d..1c458750d60 100644 --- a/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen.go +++ b/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *ScheduledQueryRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the ScheduledQueryRule resource func (rule *ScheduledQueryRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &ScheduledQueryRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ScheduledQueryRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ScheduledQueryRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ScheduledQueryRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ScheduledQueryRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *ScheduledQueryRule) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (rule *ScheduledQueryRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *ScheduledQueryRule) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *ScheduledQueryRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *ScheduledQueryRule) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *ScheduledQueryRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *ScheduledQueryRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ScheduledQueryRule) @@ -374,6 +419,10 @@ type ScheduledQueryRule_Spec struct { // Relevant only for rules of the kind LogAlert. MuteActionsDuration *string `json:"muteActionsDuration,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ScheduledQueryRuleOperatorSpec `json:"operatorSpec,omitempty"` + // OverrideQueryTimeRange: If specified then overrides the query time range (default is // WindowSize*NumberOfEvaluationPeriods). Relevant only for rules of the kind LogAlert. OverrideQueryTimeRange *string `json:"overrideQueryTimeRange,omitempty"` @@ -656,6 +705,8 @@ func (rule *ScheduledQueryRule_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "OverrideQueryTimeRange": // copying flattened property: if typedInput.Properties != nil { @@ -850,6 +901,18 @@ func (rule *ScheduledQueryRule_Spec) AssignProperties_From_ScheduledQueryRule_Sp // MuteActionsDuration rule.MuteActionsDuration = genruntime.ClonePointerToString(source.MuteActionsDuration) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ScheduledQueryRuleOperatorSpec + err := operatorSpec.AssignProperties_From_ScheduledQueryRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ScheduledQueryRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OverrideQueryTimeRange rule.OverrideQueryTimeRange = genruntime.ClonePointerToString(source.OverrideQueryTimeRange) @@ -982,6 +1045,18 @@ func (rule *ScheduledQueryRule_Spec) AssignProperties_To_ScheduledQueryRule_Spec // MuteActionsDuration destination.MuteActionsDuration = genruntime.ClonePointerToString(rule.MuteActionsDuration) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.ScheduledQueryRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_ScheduledQueryRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ScheduledQueryRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -2336,6 +2411,110 @@ func (criteria *ScheduledQueryRuleCriteria_STATUS) AssignProperties_To_Scheduled return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ScheduledQueryRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ScheduledQueryRuleOperatorSpec populates our ScheduledQueryRuleOperatorSpec from the provided source ScheduledQueryRuleOperatorSpec +func (operator *ScheduledQueryRuleOperatorSpec) AssignProperties_From_ScheduledQueryRuleOperatorSpec(source *storage.ScheduledQueryRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ScheduledQueryRuleOperatorSpec populates the provided destination ScheduledQueryRuleOperatorSpec from our ScheduledQueryRuleOperatorSpec +func (operator *ScheduledQueryRuleOperatorSpec) AssignProperties_To_ScheduledQueryRuleOperatorSpec(destination *storage.ScheduledQueryRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={0,1,2,3,4} type ScheduledQueryRuleProperties_Severity int diff --git a/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen_test.go b/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen_test.go index 386bdd6a6b3..d6e8db8dbaf 100644 --- a/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen_test.go +++ b/v2/api/insights/v1api20220615/scheduled_query_rule_types_gen_test.go @@ -1260,6 +1260,103 @@ func AddRelatedPropertyGeneratorsForScheduledQueryRuleCriteria_STATUS(gens map[s gens["AllOf"] = gen.SliceOf(Condition_STATUSGenerator()) } +func Test_ScheduledQueryRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ScheduledQueryRuleOperatorSpec to ScheduledQueryRuleOperatorSpec via AssignProperties_To_ScheduledQueryRuleOperatorSpec & AssignProperties_From_ScheduledQueryRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForScheduledQueryRuleOperatorSpec, ScheduledQueryRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForScheduledQueryRuleOperatorSpec tests if a specific instance of ScheduledQueryRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForScheduledQueryRuleOperatorSpec(subject ScheduledQueryRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ScheduledQueryRuleOperatorSpec + err := copied.AssignProperties_To_ScheduledQueryRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ScheduledQueryRuleOperatorSpec + err = actual.AssignProperties_From_ScheduledQueryRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ScheduledQueryRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ScheduledQueryRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForScheduledQueryRuleOperatorSpec, ScheduledQueryRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForScheduledQueryRuleOperatorSpec runs a test to see if a specific instance of ScheduledQueryRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForScheduledQueryRuleOperatorSpec(subject ScheduledQueryRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ScheduledQueryRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ScheduledQueryRuleOperatorSpec instances for property testing - lazily instantiated by +// ScheduledQueryRuleOperatorSpecGenerator() +var scheduledQueryRuleOperatorSpecGenerator gopter.Gen + +// ScheduledQueryRuleOperatorSpecGenerator returns a generator of ScheduledQueryRuleOperatorSpec instances for property testing. +func ScheduledQueryRuleOperatorSpecGenerator() gopter.Gen { + if scheduledQueryRuleOperatorSpecGenerator != nil { + return scheduledQueryRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + scheduledQueryRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ScheduledQueryRuleOperatorSpec{}), generators) + + return scheduledQueryRuleOperatorSpecGenerator +} + func Test_ScheduledQueryRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1546,6 +1643,7 @@ func AddIndependentPropertyGeneratorsForScheduledQueryRule_Spec(gens map[string] func AddRelatedPropertyGeneratorsForScheduledQueryRule_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.PtrOf(ActionsGenerator()) gens["Criteria"] = gen.PtrOf(ScheduledQueryRuleCriteriaGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ScheduledQueryRuleOperatorSpecGenerator()) } func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen.go b/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen.go index ae25f7069da..4539354998b 100644 --- a/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen.go +++ b/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/insights/v1api20221001/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (rule *ScheduledQueryRule) SetConditions(conditions conditions.Conditions) rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &ScheduledQueryRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ScheduledQueryRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ScheduledQueryRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ScheduledQueryRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ScheduledQueryRule{} // AzureName returns the Azure name of the resource @@ -152,18 +175,19 @@ type ScheduledQueryRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CheckWorkspaceAlertsStorageConfigured *bool `json:"checkWorkspaceAlertsStorageConfigured,omitempty"` - Criteria *ScheduledQueryRuleCriteria `json:"criteria,omitempty"` - Description *string `json:"description,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - EvaluationFrequency *string `json:"evaluationFrequency,omitempty"` - Kind *string `json:"kind,omitempty"` - Location *string `json:"location,omitempty"` - MuteActionsDuration *string `json:"muteActionsDuration,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - OverrideQueryTimeRange *string `json:"overrideQueryTimeRange,omitempty"` + AzureName string `json:"azureName,omitempty"` + CheckWorkspaceAlertsStorageConfigured *bool `json:"checkWorkspaceAlertsStorageConfigured,omitempty"` + Criteria *ScheduledQueryRuleCriteria `json:"criteria,omitempty"` + Description *string `json:"description,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + EvaluationFrequency *string `json:"evaluationFrequency,omitempty"` + Kind *string `json:"kind,omitempty"` + Location *string `json:"location,omitempty"` + MuteActionsDuration *string `json:"muteActionsDuration,omitempty"` + OperatorSpec *ScheduledQueryRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + OverrideQueryTimeRange *string `json:"overrideQueryTimeRange,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -281,6 +305,14 @@ type ScheduledQueryRuleCriteria_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220615.ScheduledQueryRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ScheduledQueryRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220615.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen_test.go b/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen_test.go index 61dcf9fae73..670951eee9d 100644 --- a/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen_test.go +++ b/v2/api/insights/v1api20220615/storage/scheduled_query_rule_types_gen_test.go @@ -735,6 +735,61 @@ func AddRelatedPropertyGeneratorsForScheduledQueryRuleCriteria_STATUS(gens map[s gens["AllOf"] = gen.SliceOf(Condition_STATUSGenerator()) } +func Test_ScheduledQueryRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ScheduledQueryRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForScheduledQueryRuleOperatorSpec, ScheduledQueryRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForScheduledQueryRuleOperatorSpec runs a test to see if a specific instance of ScheduledQueryRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForScheduledQueryRuleOperatorSpec(subject ScheduledQueryRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ScheduledQueryRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ScheduledQueryRuleOperatorSpec instances for property testing - lazily instantiated by +// ScheduledQueryRuleOperatorSpecGenerator() +var scheduledQueryRuleOperatorSpecGenerator gopter.Gen + +// ScheduledQueryRuleOperatorSpecGenerator returns a generator of ScheduledQueryRuleOperatorSpec instances for property testing. +func ScheduledQueryRuleOperatorSpecGenerator() gopter.Gen { + if scheduledQueryRuleOperatorSpecGenerator != nil { + return scheduledQueryRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + scheduledQueryRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ScheduledQueryRuleOperatorSpec{}), generators) + + return scheduledQueryRuleOperatorSpecGenerator +} + func Test_ScheduledQueryRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -928,6 +983,7 @@ func AddIndependentPropertyGeneratorsForScheduledQueryRule_Spec(gens map[string] func AddRelatedPropertyGeneratorsForScheduledQueryRule_Spec(gens map[string]gopter.Gen) { gens["Actions"] = gen.PtrOf(ActionsGenerator()) gens["Criteria"] = gen.PtrOf(ScheduledQueryRuleCriteriaGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ScheduledQueryRuleOperatorSpecGenerator()) } func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/insights/v1api20220615/storage/structure.txt b/v2/api/insights/v1api20220615/storage/structure.txt index 722626376dd..5a0ea549890 100644 --- a/v2/api/insights/v1api20220615/storage/structure.txt +++ b/v2/api/insights/v1api20220615/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-06-15" ScheduledQueryRule: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (22 properties) +├── Spec: Object (23 properties) │ ├── Actions: *Object (3 properties) │ │ ├── ActionGroupsReferences: genruntime.ResourceReference[] │ │ ├── CustomProperties: map[string]string @@ -40,6 +40,10 @@ ScheduledQueryRule: Resource │ ├── Kind: *string │ ├── Location: *string │ ├── MuteActionsDuration: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OverrideQueryTimeRange: *string │ ├── Owner: *genruntime.KnownResourceReference @@ -110,7 +114,7 @@ ScheduledQueryRule: Resource └── WindowSize: *string Webtest: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AzureName: string │ ├── Configuration: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -124,6 +128,10 @@ Webtest: Resource │ │ ├── Id: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Name: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/insights/v1api20220615/storage/webtest_types_gen.go b/v2/api/insights/v1api20220615/storage/webtest_types_gen.go index bd150118528..03cfd76fb85 100644 --- a/v2/api/insights/v1api20220615/storage/webtest_types_gen.go +++ b/v2/api/insights/v1api20220615/storage/webtest_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (webtest *Webtest) SetConditions(conditions conditions.Conditions) { webtest.Status.Conditions = conditions } +var _ configmaps.Exporter = &Webtest{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (webtest *Webtest) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Webtest{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (webtest *Webtest) SecretDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Webtest{} // AzureName returns the Azure name of the resource @@ -151,6 +174,7 @@ type Webtest_Spec struct { Location *string `json:"location,omitempty"` Locations []WebTestGeolocation `json:"Locations,omitempty"` Name *string `json:"Name,omitempty"` + OperatorSpec *WebtestOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -245,6 +269,14 @@ type WebTestGeolocation_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220615.WebtestOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebtestOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220615.WebTestProperties_Configuration type WebTestProperties_Configuration struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` diff --git a/v2/api/insights/v1api20220615/storage/webtest_types_gen_test.go b/v2/api/insights/v1api20220615/storage/webtest_types_gen_test.go index 3b726b7437a..5176313fcff 100644 --- a/v2/api/insights/v1api20220615/storage/webtest_types_gen_test.go +++ b/v2/api/insights/v1api20220615/storage/webtest_types_gen_test.go @@ -883,6 +883,61 @@ func AddRelatedPropertyGeneratorsForWebtest(gens map[string]gopter.Gen) { gens["Status"] = Webtest_STATUSGenerator() } +func Test_WebtestOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebtestOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebtestOperatorSpec runs a test to see if a specific instance of WebtestOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebtestOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebtestOperatorSpec instances for property testing - lazily instantiated by +// WebtestOperatorSpecGenerator() +var webtestOperatorSpecGenerator gopter.Gen + +// WebtestOperatorSpecGenerator returns a generator of WebtestOperatorSpec instances for property testing. +func WebtestOperatorSpecGenerator() gopter.Gen { + if webtestOperatorSpecGenerator != nil { + return webtestOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webtestOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebtestOperatorSpec{}), generators) + + return webtestOperatorSpecGenerator +} + func Test_Webtest_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1061,6 +1116,7 @@ func AddIndependentPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) { gens["Configuration"] = gen.PtrOf(WebTestProperties_ConfigurationGenerator()) gens["Locations"] = gen.SliceOf(WebTestGeolocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebtestOperatorSpecGenerator()) gens["Request"] = gen.PtrOf(WebTestProperties_RequestGenerator()) gens["ValidationRules"] = gen.PtrOf(WebTestProperties_ValidationRulesGenerator()) } diff --git a/v2/api/insights/v1api20220615/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20220615/storage/zz_generated.deepcopy.go index 52c4147b8d8..42798194a97 100644 --- a/v2/api/insights/v1api20220615/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20220615/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -540,6 +541,50 @@ func (in *ScheduledQueryRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledQueryRuleOperatorSpec) DeepCopyInto(out *ScheduledQueryRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledQueryRuleOperatorSpec. +func (in *ScheduledQueryRuleOperatorSpec) DeepCopy() *ScheduledQueryRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ScheduledQueryRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScheduledQueryRule_STATUS) DeepCopyInto(out *ScheduledQueryRule_STATUS) { *out = *in @@ -759,6 +804,11 @@ func (in *ScheduledQueryRule_Spec) DeepCopyInto(out *ScheduledQueryRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ScheduledQueryRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OverrideQueryTimeRange != nil { in, out := &in.OverrideQueryTimeRange, &out.OverrideQueryTimeRange *out = new(string) @@ -1315,6 +1365,50 @@ func (in *WebtestList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebtestOperatorSpec) DeepCopyInto(out *WebtestOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebtestOperatorSpec. +func (in *WebtestOperatorSpec) DeepCopy() *WebtestOperatorSpec { + if in == nil { + return nil + } + out := new(WebtestOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webtest_STATUS) DeepCopyInto(out *Webtest_STATUS) { *out = *in @@ -1483,6 +1577,11 @@ func (in *Webtest_Spec) DeepCopyInto(out *Webtest_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebtestOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20220615/structure.txt b/v2/api/insights/v1api20220615/structure.txt index 2220b06fcd2..82fbec0af7d 100644 --- a/v2/api/insights/v1api20220615/structure.txt +++ b/v2/api/insights/v1api20220615/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-06-15" ScheduledQueryRule: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (20 properties) +├── Spec: Object (21 properties) │ ├── Actions: *Object (2 properties) │ │ ├── ActionGroupsReferences: genruntime.ResourceReference[] │ │ └── CustomProperties: map[string]string @@ -50,6 +50,9 @@ ScheduledQueryRule: Resource │ │ └── "LogToMetric" │ ├── Location: *string │ ├── MuteActionsDuration: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OverrideQueryTimeRange: *string │ ├── Owner: *genruntime.KnownResourceReference │ ├── ScopesReferences: genruntime.ResourceReference[] @@ -143,7 +146,7 @@ ScheduledQueryRule: Resource └── WindowSize: *string Webtest: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AzureName: string │ ├── Configuration: *Object (1 property) │ │ └── WebTest: *string @@ -158,6 +161,9 @@ Webtest: Resource │ ├── Locations: Object (1 property)[] │ │ └── Id: *string │ ├── Name: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Request: *Object (6 properties) │ │ ├── FollowRedirects: *bool diff --git a/v2/api/insights/v1api20220615/webtest_types_gen.go b/v2/api/insights/v1api20220615/webtest_types_gen.go index 6f0b9280526..7af66b28854 100644 --- a/v2/api/insights/v1api20220615/webtest_types_gen.go +++ b/v2/api/insights/v1api20220615/webtest_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (webtest *Webtest) defaultAzureName() { // defaultImpl applies the code generated defaults to the Webtest resource func (webtest *Webtest) defaultImpl() { webtest.defaultAzureName() } +var _ configmaps.Exporter = &Webtest{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (webtest *Webtest) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Webtest{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (webtest *Webtest) SecretDestinationExpressions() []*core.DestinationExpression { + if webtest.Spec.OperatorSpec == nil { + return nil + } + return webtest.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Webtest{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (webtest *Webtest) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (webtest *Webtest) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){webtest.validateResourceReferences, webtest.validateOwnerReference} + return []func() (admission.Warnings, error){webtest.validateResourceReferences, webtest.validateOwnerReference, webtest.validateSecretDestinations, webtest.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (webtest *Webtest) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return webtest.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return webtest.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return webtest.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (webtest *Webtest) validateConfigMapDestinations() (admission.Warnings, error) { + if webtest.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(webtest, nil, webtest.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (webtest *Webtest) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (webtest *Webtest) validateSecretDestinations() (admission.Warnings, error) { + if webtest.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(webtest, nil, webtest.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (webtest *Webtest) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Webtest) @@ -359,6 +404,10 @@ type Webtest_Spec struct { // Name: User defined name if this WebTest. Name *string `json:"Name,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WebtestOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -589,6 +638,8 @@ func (webtest *Webtest_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": webtest.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -777,6 +828,18 @@ func (webtest *Webtest_Spec) AssignProperties_From_Webtest_Spec(source *storage. // Name webtest.Name = genruntime.ClonePointerToString(source.Name) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WebtestOperatorSpec + err := operatorSpec.AssignProperties_From_WebtestOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WebtestOperatorSpec() to populate field OperatorSpec") + } + webtest.OperatorSpec = &operatorSpec + } else { + webtest.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -896,6 +959,18 @@ func (webtest *Webtest_Spec) AssignProperties_To_Webtest_Spec(destination *stora // Name destination.Name = genruntime.ClonePointerToString(webtest.Name) + // OperatorSpec + if webtest.OperatorSpec != nil { + var operatorSpec storage.WebtestOperatorSpec + err := webtest.OperatorSpec.AssignProperties_To_WebtestOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WebtestOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = webtest.OriginalVersion() @@ -1770,6 +1845,110 @@ func (geolocation *WebTestGeolocation_STATUS) AssignProperties_To_WebTestGeoloca return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebtestOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WebtestOperatorSpec populates our WebtestOperatorSpec from the provided source WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_From_WebtestOperatorSpec(source *storage.WebtestOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WebtestOperatorSpec populates the provided destination WebtestOperatorSpec from our WebtestOperatorSpec +func (operator *WebtestOperatorSpec) AssignProperties_To_WebtestOperatorSpec(destination *storage.WebtestOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type WebTestProperties_Configuration struct { // WebTest: The XML specification of a WebTest to run against an application. WebTest *string `json:"WebTest,omitempty"` diff --git a/v2/api/insights/v1api20220615/webtest_types_gen_test.go b/v2/api/insights/v1api20220615/webtest_types_gen_test.go index 1a1df5e240e..85c412e1862 100644 --- a/v2/api/insights/v1api20220615/webtest_types_gen_test.go +++ b/v2/api/insights/v1api20220615/webtest_types_gen_test.go @@ -1473,6 +1473,103 @@ func AddRelatedPropertyGeneratorsForWebtest(gens map[string]gopter.Gen) { gens["Status"] = Webtest_STATUSGenerator() } +func Test_WebtestOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WebtestOperatorSpec to WebtestOperatorSpec via AssignProperties_To_WebtestOperatorSpec & AssignProperties_From_WebtestOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWebtestOperatorSpec tests if a specific instance of WebtestOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WebtestOperatorSpec + err := copied.AssignProperties_To_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WebtestOperatorSpec + err = actual.AssignProperties_From_WebtestOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WebtestOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebtestOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebtestOperatorSpec, WebtestOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebtestOperatorSpec runs a test to see if a specific instance of WebtestOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebtestOperatorSpec(subject WebtestOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebtestOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebtestOperatorSpec instances for property testing - lazily instantiated by +// WebtestOperatorSpecGenerator() +var webtestOperatorSpecGenerator gopter.Gen + +// WebtestOperatorSpecGenerator returns a generator of WebtestOperatorSpec instances for property testing. +func WebtestOperatorSpecGenerator() gopter.Gen { + if webtestOperatorSpecGenerator != nil { + return webtestOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webtestOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebtestOperatorSpec{}), generators) + + return webtestOperatorSpecGenerator +} + func Test_Webtest_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1734,6 +1831,7 @@ func AddIndependentPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) func AddRelatedPropertyGeneratorsForWebtest_Spec(gens map[string]gopter.Gen) { gens["Configuration"] = gen.PtrOf(WebTestProperties_ConfigurationGenerator()) gens["Locations"] = gen.SliceOf(WebTestGeolocationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebtestOperatorSpecGenerator()) gens["Request"] = gen.PtrOf(WebTestProperties_RequestGenerator()) gens["ValidationRules"] = gen.PtrOf(WebTestProperties_ValidationRulesGenerator()) } diff --git a/v2/api/insights/v1api20220615/zz_generated.deepcopy.go b/v2/api/insights/v1api20220615/zz_generated.deepcopy.go index 1dc59bc8635..875dbe715a5 100644 --- a/v2/api/insights/v1api20220615/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20220615/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220615 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -456,6 +457,43 @@ func (in *ScheduledQueryRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScheduledQueryRuleOperatorSpec) DeepCopyInto(out *ScheduledQueryRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScheduledQueryRuleOperatorSpec. +func (in *ScheduledQueryRuleOperatorSpec) DeepCopy() *ScheduledQueryRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ScheduledQueryRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScheduledQueryRule_STATUS) DeepCopyInto(out *ScheduledQueryRule_STATUS) { *out = *in @@ -668,6 +706,11 @@ func (in *ScheduledQueryRule_Spec) DeepCopyInto(out *ScheduledQueryRule_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ScheduledQueryRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OverrideQueryTimeRange != nil { in, out := &in.OverrideQueryTimeRange, &out.OverrideQueryTimeRange *out = new(string) @@ -1140,6 +1183,43 @@ func (in *WebtestList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebtestOperatorSpec) DeepCopyInto(out *WebtestOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebtestOperatorSpec. +func (in *WebtestOperatorSpec) DeepCopy() *WebtestOperatorSpec { + if in == nil { + return nil + } + out := new(WebtestOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Webtest_STATUS) DeepCopyInto(out *Webtest_STATUS) { *out = *in @@ -1301,6 +1381,11 @@ func (in *Webtest_Spec) DeepCopyInto(out *Webtest_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebtestOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20221001/autoscale_setting_types_gen.go b/v2/api/insights/v1api20221001/autoscale_setting_types_gen.go index 53aca99ced5..f9aa3d1157c 100644 --- a/v2/api/insights/v1api20221001/autoscale_setting_types_gen.go +++ b/v2/api/insights/v1api20221001/autoscale_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (setting *AutoscaleSetting) defaultAzureName() { // defaultImpl applies the code generated defaults to the AutoscaleSetting resource func (setting *AutoscaleSetting) defaultImpl() { setting.defaultAzureName() } +var _ configmaps.Exporter = &AutoscaleSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *AutoscaleSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AutoscaleSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *AutoscaleSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &AutoscaleSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (setting *AutoscaleSetting) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (setting *AutoscaleSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (setting *AutoscaleSetting) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *AutoscaleSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (setting *AutoscaleSetting) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *AutoscaleSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *AutoscaleSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AutoscaleSetting) @@ -348,6 +393,10 @@ type AutoscaleSetting_Spec struct { // Notifications: the collection of notifications. Notifications []AutoscaleNotification `json:"notifications,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AutoscaleSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -508,6 +557,8 @@ func (setting *AutoscaleSetting_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -652,6 +703,18 @@ func (setting *AutoscaleSetting_Spec) AssignProperties_From_AutoscaleSetting_Spe setting.Notifications = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AutoscaleSettingOperatorSpec + err := operatorSpec.AssignProperties_From_AutoscaleSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AutoscaleSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -748,6 +811,18 @@ func (setting *AutoscaleSetting_Spec) AssignProperties_To_AutoscaleSetting_Spec( destination.Notifications = nil } + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.AutoscaleSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_AutoscaleSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AutoscaleSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -2316,6 +2391,110 @@ func (profile *AutoscaleProfile_STATUS) AssignProperties_To_AutoscaleProfile_STA return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AutoscaleSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AutoscaleSettingOperatorSpec populates our AutoscaleSettingOperatorSpec from the provided source AutoscaleSettingOperatorSpec +func (operator *AutoscaleSettingOperatorSpec) AssignProperties_From_AutoscaleSettingOperatorSpec(source *storage.AutoscaleSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AutoscaleSettingOperatorSpec populates the provided destination AutoscaleSettingOperatorSpec from our AutoscaleSettingOperatorSpec +func (operator *AutoscaleSettingOperatorSpec) AssignProperties_To_AutoscaleSettingOperatorSpec(destination *storage.AutoscaleSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The parameters for enabling predictive autoscale. type PredictiveAutoscalePolicy struct { // ScaleLookAheadTime: the amount of time to specify by which instances are launched in advance. It must be between 1 diff --git a/v2/api/insights/v1api20221001/autoscale_setting_types_gen_test.go b/v2/api/insights/v1api20221001/autoscale_setting_types_gen_test.go index e8bc348a5d8..c638d1aed10 100644 --- a/v2/api/insights/v1api20221001/autoscale_setting_types_gen_test.go +++ b/v2/api/insights/v1api20221001/autoscale_setting_types_gen_test.go @@ -639,6 +639,103 @@ func AddRelatedPropertyGeneratorsForAutoscaleSetting(gens map[string]gopter.Gen) gens["Status"] = Autoscalesetting_STATUSGenerator() } +func Test_AutoscaleSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AutoscaleSettingOperatorSpec to AutoscaleSettingOperatorSpec via AssignProperties_To_AutoscaleSettingOperatorSpec & AssignProperties_From_AutoscaleSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAutoscaleSettingOperatorSpec, AutoscaleSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAutoscaleSettingOperatorSpec tests if a specific instance of AutoscaleSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAutoscaleSettingOperatorSpec(subject AutoscaleSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AutoscaleSettingOperatorSpec + err := copied.AssignProperties_To_AutoscaleSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AutoscaleSettingOperatorSpec + err = actual.AssignProperties_From_AutoscaleSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AutoscaleSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AutoscaleSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAutoscaleSettingOperatorSpec, AutoscaleSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAutoscaleSettingOperatorSpec runs a test to see if a specific instance of AutoscaleSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAutoscaleSettingOperatorSpec(subject AutoscaleSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AutoscaleSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AutoscaleSettingOperatorSpec instances for property testing - lazily instantiated by +// AutoscaleSettingOperatorSpecGenerator() +var autoscaleSettingOperatorSpecGenerator gopter.Gen + +// AutoscaleSettingOperatorSpecGenerator returns a generator of AutoscaleSettingOperatorSpec instances for property testing. +func AutoscaleSettingOperatorSpecGenerator() gopter.Gen { + if autoscaleSettingOperatorSpecGenerator != nil { + return autoscaleSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + autoscaleSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AutoscaleSettingOperatorSpec{}), generators) + + return autoscaleSettingOperatorSpecGenerator +} + func Test_AutoscaleSetting_Spec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -761,6 +858,7 @@ func AddIndependentPropertyGeneratorsForAutoscaleSetting_Spec(gens map[string]go // AddRelatedPropertyGeneratorsForAutoscaleSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAutoscaleSetting_Spec(gens map[string]gopter.Gen) { gens["Notifications"] = gen.SliceOf(AutoscaleNotificationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AutoscaleSettingOperatorSpecGenerator()) gens["PredictiveAutoscalePolicy"] = gen.PtrOf(PredictiveAutoscalePolicyGenerator()) gens["Profiles"] = gen.SliceOf(AutoscaleProfileGenerator()) } diff --git a/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen.go b/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen.go index 7e93a085bbf..48f1ed6dc79 100644 --- a/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen.go +++ b/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *AutoscaleSetting) SetConditions(conditions conditions.Conditions) setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &AutoscaleSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *AutoscaleSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AutoscaleSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *AutoscaleSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AutoscaleSetting{} // AzureName returns the Azure name of the resource @@ -148,12 +171,13 @@ const APIVersion_Value = APIVersion("2022-10-01") type AutoscaleSetting_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Location *string `json:"location,omitempty"` - Name *string `json:"name,omitempty"` - Notifications []AutoscaleNotification `json:"notifications,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Location *string `json:"location,omitempty"` + Name *string `json:"name,omitempty"` + Notifications []AutoscaleNotification `json:"notifications,omitempty"` + OperatorSpec *AutoscaleSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -269,6 +293,14 @@ type AutoscaleProfile_STATUS struct { Rules []ScaleRule_STATUS `json:"rules,omitempty"` } +// Storage version of v1api20221001.AutoscaleSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AutoscaleSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20221001.PredictiveAutoscalePolicy // The parameters for enabling predictive autoscale. type PredictiveAutoscalePolicy struct { diff --git a/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen_test.go b/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen_test.go index d379b0cf973..20e3279545b 100644 --- a/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen_test.go +++ b/v2/api/insights/v1api20221001/storage/autoscale_setting_types_gen_test.go @@ -385,6 +385,61 @@ func AddRelatedPropertyGeneratorsForAutoscaleSetting(gens map[string]gopter.Gen) gens["Status"] = Autoscalesetting_STATUSGenerator() } +func Test_AutoscaleSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AutoscaleSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAutoscaleSettingOperatorSpec, AutoscaleSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAutoscaleSettingOperatorSpec runs a test to see if a specific instance of AutoscaleSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAutoscaleSettingOperatorSpec(subject AutoscaleSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AutoscaleSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AutoscaleSettingOperatorSpec instances for property testing - lazily instantiated by +// AutoscaleSettingOperatorSpecGenerator() +var autoscaleSettingOperatorSpecGenerator gopter.Gen + +// AutoscaleSettingOperatorSpecGenerator returns a generator of AutoscaleSettingOperatorSpec instances for property testing. +func AutoscaleSettingOperatorSpecGenerator() gopter.Gen { + if autoscaleSettingOperatorSpecGenerator != nil { + return autoscaleSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + autoscaleSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AutoscaleSettingOperatorSpec{}), generators) + + return autoscaleSettingOperatorSpecGenerator +} + func Test_AutoscaleSetting_Spec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -466,6 +521,7 @@ func AddIndependentPropertyGeneratorsForAutoscaleSetting_Spec(gens map[string]go // AddRelatedPropertyGeneratorsForAutoscaleSetting_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAutoscaleSetting_Spec(gens map[string]gopter.Gen) { gens["Notifications"] = gen.SliceOf(AutoscaleNotificationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(AutoscaleSettingOperatorSpecGenerator()) gens["PredictiveAutoscalePolicy"] = gen.PtrOf(PredictiveAutoscalePolicyGenerator()) gens["Profiles"] = gen.SliceOf(AutoscaleProfileGenerator()) } diff --git a/v2/api/insights/v1api20221001/storage/structure.txt b/v2/api/insights/v1api20221001/storage/structure.txt index 4e2ba8f01da..29ce98e61e4 100644 --- a/v2/api/insights/v1api20221001/storage/structure.txt +++ b/v2/api/insights/v1api20221001/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-10-01" AutoscaleSetting: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── Enabled: *bool │ ├── Location: *string @@ -22,6 +22,10 @@ AutoscaleSetting: Resource │ │ ├── Properties: map[string]string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── ServiceUri: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PredictiveAutoscalePolicy: *Object (3 properties) diff --git a/v2/api/insights/v1api20221001/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20221001/storage/zz_generated.deepcopy.go index 4741ce9437c..e558df44d8d 100644 --- a/v2/api/insights/v1api20221001/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20221001/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -250,6 +251,50 @@ func (in *AutoscaleSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscaleSettingOperatorSpec) DeepCopyInto(out *AutoscaleSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscaleSettingOperatorSpec. +func (in *AutoscaleSettingOperatorSpec) DeepCopy() *AutoscaleSettingOperatorSpec { + if in == nil { + return nil + } + out := new(AutoscaleSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AutoscaleSetting_Spec) DeepCopyInto(out *AutoscaleSetting_Spec) { *out = *in @@ -275,6 +320,11 @@ func (in *AutoscaleSetting_Spec) DeepCopyInto(out *AutoscaleSetting_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AutoscaleSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20221001/structure.txt b/v2/api/insights/v1api20221001/structure.txt index a3e5a6c2c89..04ba8fbaa1a 100644 --- a/v2/api/insights/v1api20221001/structure.txt +++ b/v2/api/insights/v1api20221001/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-10-01" AutoscaleSetting: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── Enabled: *bool │ ├── Location: *string @@ -20,6 +20,9 @@ AutoscaleSetting: Resource │ │ └── Webhooks: Object (2 properties)[] │ │ ├── Properties: map[string]string │ │ └── ServiceUri: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PredictiveAutoscalePolicy: *Object (2 properties) │ │ ├── ScaleLookAheadTime: *string diff --git a/v2/api/insights/v1api20221001/zz_generated.deepcopy.go b/v2/api/insights/v1api20221001/zz_generated.deepcopy.go index f3efd9b9b35..dad8ee3835b 100644 --- a/v2/api/insights/v1api20221001/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20221001/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20221001 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -222,6 +223,43 @@ func (in *AutoscaleSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscaleSettingOperatorSpec) DeepCopyInto(out *AutoscaleSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscaleSettingOperatorSpec. +func (in *AutoscaleSettingOperatorSpec) DeepCopy() *AutoscaleSettingOperatorSpec { + if in == nil { + return nil + } + out := new(AutoscaleSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AutoscaleSetting_Spec) DeepCopyInto(out *AutoscaleSetting_Spec) { *out = *in @@ -247,6 +285,11 @@ func (in *AutoscaleSetting_Spec) DeepCopyInto(out *AutoscaleSetting_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AutoscaleSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20230101/action_group_types_gen.go b/v2/api/insights/v1api20230101/action_group_types_gen.go index 7f47399400e..ea54850533d 100644 --- a/v2/api/insights/v1api20230101/action_group_types_gen.go +++ b/v2/api/insights/v1api20230101/action_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *ActionGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the ActionGroup resource func (group *ActionGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &ActionGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ActionGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ActionGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ActionGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ActionGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *ActionGroup) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (group *ActionGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *ActionGroup) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *ActionGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *ActionGroup) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *ActionGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *ActionGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ActionGroup) @@ -369,6 +414,10 @@ type ActionGroup_Spec struct { // LogicAppReceivers: The list of logic app receivers that are part of this action group. LogicAppReceivers []LogicAppReceiver `json:"logicAppReceivers,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ActionGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -661,6 +710,8 @@ func (group *ActionGroup_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -937,6 +988,18 @@ func (group *ActionGroup_Spec) AssignProperties_From_ActionGroup_Spec(source *st group.LogicAppReceivers = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ActionGroupOperatorSpec + err := operatorSpec.AssignProperties_From_ActionGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ActionGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1177,6 +1240,18 @@ func (group *ActionGroup_Spec) AssignProperties_To_ActionGroup_Spec(destination destination.LogicAppReceivers = nil } + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.ActionGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_ActionGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ActionGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -2298,6 +2373,110 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-01-01") +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ActionGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ActionGroupOperatorSpec populates our ActionGroupOperatorSpec from the provided source ActionGroupOperatorSpec +func (operator *ActionGroupOperatorSpec) AssignProperties_From_ActionGroupOperatorSpec(source *storage.ActionGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ActionGroupOperatorSpec populates the provided destination ActionGroupOperatorSpec from our ActionGroupOperatorSpec +func (operator *ActionGroupOperatorSpec) AssignProperties_To_ActionGroupOperatorSpec(destination *storage.ActionGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An arm role receiver. type ArmRoleReceiver struct { // +kubebuilder:validation:Required diff --git a/v2/api/insights/v1api20230101/action_group_types_gen_test.go b/v2/api/insights/v1api20230101/action_group_types_gen_test.go index a5270b1d8cf..5792894c704 100644 --- a/v2/api/insights/v1api20230101/action_group_types_gen_test.go +++ b/v2/api/insights/v1api20230101/action_group_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForActionGroup(gens map[string]gopter.Gen) { gens["Status"] = ActionGroupResource_STATUSGenerator() } +func Test_ActionGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ActionGroupOperatorSpec to ActionGroupOperatorSpec via AssignProperties_To_ActionGroupOperatorSpec & AssignProperties_From_ActionGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForActionGroupOperatorSpec, ActionGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForActionGroupOperatorSpec tests if a specific instance of ActionGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForActionGroupOperatorSpec(subject ActionGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ActionGroupOperatorSpec + err := copied.AssignProperties_To_ActionGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ActionGroupOperatorSpec + err = actual.AssignProperties_From_ActionGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ActionGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ActionGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForActionGroupOperatorSpec, ActionGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForActionGroupOperatorSpec runs a test to see if a specific instance of ActionGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForActionGroupOperatorSpec(subject ActionGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ActionGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ActionGroupOperatorSpec instances for property testing - lazily instantiated by +// ActionGroupOperatorSpecGenerator() +var actionGroupOperatorSpecGenerator gopter.Gen + +// ActionGroupOperatorSpecGenerator returns a generator of ActionGroupOperatorSpec instances for property testing. +func ActionGroupOperatorSpecGenerator() gopter.Gen { + if actionGroupOperatorSpecGenerator != nil { + return actionGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + actionGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ActionGroupOperatorSpec{}), generators) + + return actionGroupOperatorSpecGenerator +} + func Test_ActionGroupResource_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -426,6 +523,7 @@ func AddRelatedPropertyGeneratorsForActionGroup_Spec(gens map[string]gopter.Gen) gens["EventHubReceivers"] = gen.SliceOf(EventHubReceiverGenerator()) gens["ItsmReceivers"] = gen.SliceOf(ItsmReceiverGenerator()) gens["LogicAppReceivers"] = gen.SliceOf(LogicAppReceiverGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ActionGroupOperatorSpecGenerator()) gens["SmsReceivers"] = gen.SliceOf(SmsReceiverGenerator()) gens["VoiceReceivers"] = gen.SliceOf(VoiceReceiverGenerator()) gens["WebhookReceivers"] = gen.SliceOf(WebhookReceiverGenerator()) diff --git a/v2/api/insights/v1api20230101/storage/action_group_types_gen.go b/v2/api/insights/v1api20230101/storage/action_group_types_gen.go index d2f90cc6315..c82502da9d8 100644 --- a/v2/api/insights/v1api20230101/storage/action_group_types_gen.go +++ b/v2/api/insights/v1api20230101/storage/action_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *ActionGroup) SetConditions(conditions conditions.Conditions) { group.Status.Conditions = conditions } +var _ configmaps.Exporter = &ActionGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ActionGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ActionGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ActionGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ActionGroup{} // AzureName returns the Azure name of the resource @@ -147,15 +170,16 @@ type ActionGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EmailReceivers []EmailReceiver `json:"emailReceivers,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - EventHubReceivers []EventHubReceiver `json:"eventHubReceivers,omitempty"` - GroupShortName *string `json:"groupShortName,omitempty"` - ItsmReceivers []ItsmReceiver `json:"itsmReceivers,omitempty"` - Location *string `json:"location,omitempty"` - LogicAppReceivers []LogicAppReceiver `json:"logicAppReceivers,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EmailReceivers []EmailReceiver `json:"emailReceivers,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + EventHubReceivers []EventHubReceiver `json:"eventHubReceivers,omitempty"` + GroupShortName *string `json:"groupShortName,omitempty"` + ItsmReceivers []ItsmReceiver `json:"itsmReceivers,omitempty"` + Location *string `json:"location,omitempty"` + LogicAppReceivers []LogicAppReceiver `json:"logicAppReceivers,omitempty"` + OperatorSpec *ActionGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -240,6 +264,14 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-01-01") +// Storage version of v1api20230101.ActionGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ActionGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.ArmRoleReceiver // An arm role receiver. type ArmRoleReceiver struct { diff --git a/v2/api/insights/v1api20230101/storage/action_group_types_gen_test.go b/v2/api/insights/v1api20230101/storage/action_group_types_gen_test.go index 1a294b919bb..3afb667b1eb 100644 --- a/v2/api/insights/v1api20230101/storage/action_group_types_gen_test.go +++ b/v2/api/insights/v1api20230101/storage/action_group_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForActionGroup(gens map[string]gopter.Gen) { gens["Status"] = ActionGroupResource_STATUSGenerator() } +func Test_ActionGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ActionGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForActionGroupOperatorSpec, ActionGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForActionGroupOperatorSpec runs a test to see if a specific instance of ActionGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForActionGroupOperatorSpec(subject ActionGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ActionGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ActionGroupOperatorSpec instances for property testing - lazily instantiated by +// ActionGroupOperatorSpecGenerator() +var actionGroupOperatorSpecGenerator gopter.Gen + +// ActionGroupOperatorSpecGenerator returns a generator of ActionGroupOperatorSpec instances for property testing. +func ActionGroupOperatorSpecGenerator() gopter.Gen { + if actionGroupOperatorSpecGenerator != nil { + return actionGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + actionGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ActionGroupOperatorSpec{}), generators) + + return actionGroupOperatorSpecGenerator +} + func Test_ActionGroupResource_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -257,6 +312,7 @@ func AddRelatedPropertyGeneratorsForActionGroup_Spec(gens map[string]gopter.Gen) gens["EventHubReceivers"] = gen.SliceOf(EventHubReceiverGenerator()) gens["ItsmReceivers"] = gen.SliceOf(ItsmReceiverGenerator()) gens["LogicAppReceivers"] = gen.SliceOf(LogicAppReceiverGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ActionGroupOperatorSpecGenerator()) gens["SmsReceivers"] = gen.SliceOf(SmsReceiverGenerator()) gens["VoiceReceivers"] = gen.SliceOf(VoiceReceiverGenerator()) gens["WebhookReceivers"] = gen.SliceOf(WebhookReceiverGenerator()) diff --git a/v2/api/insights/v1api20230101/storage/structure.txt b/v2/api/insights/v1api20230101/storage/structure.txt index 14d176f6276..698d2511e82 100644 --- a/v2/api/insights/v1api20230101/storage/structure.txt +++ b/v2/api/insights/v1api20230101/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-01-01" ActionGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── ArmRoleReceivers: Object (4 properties)[] │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag @@ -61,6 +61,10 @@ ActionGroup: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── ResourceReference: *genruntime.ResourceReference │ │ └── UseCommonAlertSchema: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/insights/v1api20230101/storage/zz_generated.deepcopy.go b/v2/api/insights/v1api20230101/storage/zz_generated.deepcopy.go index 04dd7dcf798..2b1820bacdf 100644 --- a/v2/api/insights/v1api20230101/storage/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20230101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *ActionGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionGroupOperatorSpec) DeepCopyInto(out *ActionGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionGroupOperatorSpec. +func (in *ActionGroupOperatorSpec) DeepCopy() *ActionGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ActionGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ActionGroupResource_STATUS) DeepCopyInto(out *ActionGroupResource_STATUS) { *out = *in @@ -291,6 +336,11 @@ func (in *ActionGroup_Spec) DeepCopyInto(out *ActionGroup_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ActionGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/insights/v1api20230101/structure.txt b/v2/api/insights/v1api20230101/structure.txt index 6b3cf0c5a76..cf6dee9292b 100644 --- a/v2/api/insights/v1api20230101/structure.txt +++ b/v2/api/insights/v1api20230101/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-01-01" ActionGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── ArmRoleReceivers: Object (3 properties)[] │ │ ├── Name: *string │ │ ├── RoleId: *string @@ -54,6 +54,9 @@ ActionGroup: Resource │ │ ├── Name: *string │ │ ├── ResourceReference: *genruntime.ResourceReference │ │ └── UseCommonAlertSchema: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── SmsReceivers: Object (3 properties)[] │ │ ├── CountryCode: *string diff --git a/v2/api/insights/v1api20230101/zz_generated.deepcopy.go b/v2/api/insights/v1api20230101/zz_generated.deepcopy.go index d029efd0e38..110f52c1064 100644 --- a/v2/api/insights/v1api20230101/zz_generated.deepcopy.go +++ b/v2/api/insights/v1api20230101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *ActionGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ActionGroupOperatorSpec) DeepCopyInto(out *ActionGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActionGroupOperatorSpec. +func (in *ActionGroupOperatorSpec) DeepCopy() *ActionGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ActionGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ActionGroupResource_STATUS) DeepCopyInto(out *ActionGroupResource_STATUS) { *out = *in @@ -284,6 +322,11 @@ func (in *ActionGroup_Spec) DeepCopyInto(out *ActionGroup_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ActionGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/keyvault/v1api20210401preview/storage/structure.txt b/v2/api/keyvault/v1api20210401preview/storage/structure.txt index 587c4dcd7ab..1e90575798d 100644 --- a/v2/api/keyvault/v1api20210401preview/storage/structure.txt +++ b/v2/api/keyvault/v1api20210401preview/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2021-04-01-preview" Vault: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (16 properties) @@ -139,6 +143,7 @@ augmentConversionForSku: Interface augmentConversionForSku_STATUS: Interface augmentConversionForSystemData_STATUS: Interface augmentConversionForVault: Interface +augmentConversionForVaultOperatorSpec: Interface augmentConversionForVaultProperties: Interface augmentConversionForVaultProperties_STATUS: Interface augmentConversionForVault_STATUS: Interface diff --git a/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen.go b/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen.go index da7ca833fe7..226a545a189 100644 --- a/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen.go +++ b/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/keyvault/v1api20230701/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (vault *Vault) ConvertTo(hub conversion.Hub) error { return vault.AssignProperties_To_Vault(destination) } +var _ configmaps.Exporter = &Vault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *Vault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Vault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *Vault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Vault{} // AzureName returns the Azure name of the resource @@ -241,9 +264,10 @@ type augmentConversionForVault interface { type Vault_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VaultOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -316,6 +340,18 @@ func (vault *Vault_Spec) AssignProperties_From_Vault_Spec(source *storage.Vault_ // Location vault.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VaultOperatorSpec + err := operatorSpec.AssignProperties_From_VaultOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VaultOperatorSpec() to populate field OperatorSpec") + } + vault.OperatorSpec = &operatorSpec + } else { + vault.OperatorSpec = nil + } + // OriginalVersion vault.OriginalVersion = source.OriginalVersion @@ -373,6 +409,18 @@ func (vault *Vault_Spec) AssignProperties_To_Vault_Spec(destination *storage.Vau // Location destination.Location = genruntime.ClonePointerToString(vault.Location) + // OperatorSpec + if vault.OperatorSpec != nil { + var operatorSpec storage.VaultOperatorSpec + err := vault.OperatorSpec.AssignProperties_To_VaultOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VaultOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = vault.OriginalVersion @@ -725,6 +773,136 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination return nil } +// Storage version of v1api20210401preview.VaultOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VaultOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VaultOperatorSpec populates our VaultOperatorSpec from the provided source VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_From_VaultOperatorSpec(source *storage.VaultOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForVaultOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVaultOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_VaultOperatorSpec populates the provided destination VaultOperatorSpec from our VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_To_VaultOperatorSpec(destination *storage.VaultOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForVaultOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForVaultOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210401preview.VaultProperties // Properties of the vault type VaultProperties struct { @@ -1648,6 +1826,11 @@ type augmentConversionForSystemData_STATUS interface { AssignPropertiesTo(dst *storage.SystemData_STATUS) error } +type augmentConversionForVaultOperatorSpec interface { + AssignPropertiesFrom(src *storage.VaultOperatorSpec) error + AssignPropertiesTo(dst *storage.VaultOperatorSpec) error +} + type augmentConversionForVaultProperties interface { AssignPropertiesFrom(src *storage.VaultProperties) error AssignPropertiesTo(dst *storage.VaultProperties) error diff --git a/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen_test.go b/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen_test.go index 30494989c57..2a22acd38db 100644 --- a/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen_test.go +++ b/v2/api/keyvault/v1api20210401preview/storage/vault_types_gen_test.go @@ -1693,6 +1693,102 @@ func AddRelatedPropertyGeneratorsForVault(gens map[string]gopter.Gen) { gens["Status"] = Vault_STATUSGenerator() } +func Test_VaultOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VaultOperatorSpec to VaultOperatorSpec via AssignProperties_To_VaultOperatorSpec & AssignProperties_From_VaultOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVaultOperatorSpec tests if a specific instance of VaultOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VaultOperatorSpec + err := copied.AssignProperties_To_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VaultOperatorSpec + err = actual.AssignProperties_From_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VaultOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VaultOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVaultOperatorSpec runs a test to see if a specific instance of VaultOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VaultOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VaultOperatorSpec instances for property testing - lazily instantiated by VaultOperatorSpecGenerator() +var vaultOperatorSpecGenerator gopter.Gen + +// VaultOperatorSpecGenerator returns a generator of VaultOperatorSpec instances for property testing. +func VaultOperatorSpecGenerator() gopter.Gen { + if vaultOperatorSpecGenerator != nil { + return vaultOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + vaultOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VaultOperatorSpec{}), generators) + + return vaultOperatorSpecGenerator +} + func Test_VaultProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2193,6 +2289,7 @@ func AddIndependentPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForVault_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VaultOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(VaultPropertiesGenerator()) } diff --git a/v2/api/keyvault/v1api20210401preview/storage/zz_generated.deepcopy.go b/v2/api/keyvault/v1api20210401preview/storage/zz_generated.deepcopy.go index a9aafca8b19..fec43ed5de4 100644 --- a/v2/api/keyvault/v1api20210401preview/storage/zz_generated.deepcopy.go +++ b/v2/api/keyvault/v1api20210401preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -630,6 +631,50 @@ func (in *VaultList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultOperatorSpec) DeepCopyInto(out *VaultOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultOperatorSpec. +func (in *VaultOperatorSpec) DeepCopy() *VaultOperatorSpec { + if in == nil { + return nil + } + out := new(VaultOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VaultProperties) DeepCopyInto(out *VaultProperties) { *out = *in @@ -909,6 +954,11 @@ func (in *Vault_Spec) DeepCopyInto(out *Vault_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VaultOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/keyvault/v1api20210401preview/structure.txt b/v2/api/keyvault/v1api20210401preview/structure.txt index 0d35db71caf..563714f89a7 100644 --- a/v2/api/keyvault/v1api20210401preview/structure.txt +++ b/v2/api/keyvault/v1api20210401preview/structure.txt @@ -5,10 +5,13 @@ APIVersion: Enum (1 value) └── "2021-04-01-preview" Vault: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z0-9-]{3,24}$" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (15 properties) │ │ ├── AccessPolicies: Object (7 properties)[] diff --git a/v2/api/keyvault/v1api20210401preview/vault_types_gen.go b/v2/api/keyvault/v1api20210401preview/vault_types_gen.go index 64caa6fa4e1..37b16d8dbdc 100644 --- a/v2/api/keyvault/v1api20210401preview/vault_types_gen.go +++ b/v2/api/keyvault/v1api20210401preview/vault_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +108,26 @@ func (vault *Vault) defaultAzureName() { // defaultImpl applies the code generated defaults to the Vault resource func (vault *Vault) defaultImpl() { vault.defaultAzureName() } +var _ configmaps.Exporter = &Vault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *Vault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Vault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *Vault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Vault{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (vault *Vault) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (vault *Vault) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateSecretDestinations, vault.validateConfigMapDestinations, vault.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -231,12 +253,26 @@ func (vault *Vault) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return vault.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return vault.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (vault *Vault) validateConfigMapDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (vault *Vault) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&vault.Spec) @@ -260,6 +296,14 @@ func (vault *Vault) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (vault *Vault) validateSecretDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (vault *Vault) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Vault) @@ -356,6 +400,10 @@ type Vault_Spec struct { // Location: The supported Azure location where the key vault should be created. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VaultOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -429,6 +477,8 @@ func (vault *Vault_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc vault.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": vault.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -517,6 +567,18 @@ func (vault *Vault_Spec) AssignProperties_From_Vault_Spec(source *storage.Vault_ // Location vault.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VaultOperatorSpec + err := operatorSpec.AssignProperties_From_VaultOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VaultOperatorSpec() to populate field OperatorSpec") + } + vault.OperatorSpec = &operatorSpec + } else { + vault.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -555,6 +617,18 @@ func (vault *Vault_Spec) AssignProperties_To_Vault_Spec(destination *storage.Vau // Location destination.Location = genruntime.ClonePointerToString(vault.Location) + // OperatorSpec + if vault.OperatorSpec != nil { + var operatorSpec storage.VaultOperatorSpec + err := vault.OperatorSpec.AssignProperties_To_VaultOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VaultOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = vault.OriginalVersion() @@ -1018,6 +1092,110 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VaultOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VaultOperatorSpec populates our VaultOperatorSpec from the provided source VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_From_VaultOperatorSpec(source *storage.VaultOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VaultOperatorSpec populates the provided destination VaultOperatorSpec from our VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_To_VaultOperatorSpec(destination *storage.VaultOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties of the vault type VaultProperties struct { // AccessPolicies: An array of 0 to 1024 identities that have access to the key vault. All identities in the array must use diff --git a/v2/api/keyvault/v1api20210401preview/vault_types_gen_test.go b/v2/api/keyvault/v1api20210401preview/vault_types_gen_test.go index 5405f2a1e0f..1ff377d2510 100644 --- a/v2/api/keyvault/v1api20210401preview/vault_types_gen_test.go +++ b/v2/api/keyvault/v1api20210401preview/vault_types_gen_test.go @@ -1822,6 +1822,102 @@ func AddRelatedPropertyGeneratorsForVault(gens map[string]gopter.Gen) { gens["Status"] = Vault_STATUSGenerator() } +func Test_VaultOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VaultOperatorSpec to VaultOperatorSpec via AssignProperties_To_VaultOperatorSpec & AssignProperties_From_VaultOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVaultOperatorSpec tests if a specific instance of VaultOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401ps.VaultOperatorSpec + err := copied.AssignProperties_To_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VaultOperatorSpec + err = actual.AssignProperties_From_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VaultOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VaultOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVaultOperatorSpec runs a test to see if a specific instance of VaultOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VaultOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VaultOperatorSpec instances for property testing - lazily instantiated by VaultOperatorSpecGenerator() +var vaultOperatorSpecGenerator gopter.Gen + +// VaultOperatorSpecGenerator returns a generator of VaultOperatorSpec instances for property testing. +func VaultOperatorSpecGenerator() gopter.Gen { + if vaultOperatorSpecGenerator != nil { + return vaultOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + vaultOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VaultOperatorSpec{}), generators) + + return vaultOperatorSpecGenerator +} + func Test_VaultProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2329,6 +2425,7 @@ func AddIndependentPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForVault_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VaultOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(VaultPropertiesGenerator()) } diff --git a/v2/api/keyvault/v1api20210401preview/zz_generated.deepcopy.go b/v2/api/keyvault/v1api20210401preview/zz_generated.deepcopy.go index eef336d728a..a441a3a1ffb 100644 --- a/v2/api/keyvault/v1api20210401preview/zz_generated.deepcopy.go +++ b/v2/api/keyvault/v1api20210401preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210401preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -532,6 +533,43 @@ func (in *VaultList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultOperatorSpec) DeepCopyInto(out *VaultOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultOperatorSpec. +func (in *VaultOperatorSpec) DeepCopy() *VaultOperatorSpec { + if in == nil { + return nil + } + out := new(VaultOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VaultProperties) DeepCopyInto(out *VaultProperties) { *out = *in @@ -790,6 +828,11 @@ func (in *Vault_Spec) DeepCopyInto(out *Vault_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VaultOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/keyvault/v1api20230701/storage/structure.txt b/v2/api/keyvault/v1api20230701/storage/structure.txt index 91a24a5d129..272378be5b6 100644 --- a/v2/api/keyvault/v1api20230701/storage/structure.txt +++ b/v2/api/keyvault/v1api20230701/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2023-07-01" Vault: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (17 properties) diff --git a/v2/api/keyvault/v1api20230701/storage/vault_types_gen.go b/v2/api/keyvault/v1api20230701/storage/vault_types_gen.go index 95592fdd388..6f7b67fa88b 100644 --- a/v2/api/keyvault/v1api20230701/storage/vault_types_gen.go +++ b/v2/api/keyvault/v1api20230701/storage/vault_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (vault *Vault) SetConditions(conditions conditions.Conditions) { vault.Status.Conditions = conditions } +var _ configmaps.Exporter = &Vault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *Vault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Vault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *Vault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Vault{} // AzureName returns the Azure name of the resource @@ -148,9 +171,10 @@ const APIVersion_Value = APIVersion("2023-07-01") type Vault_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *VaultOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -228,6 +252,14 @@ type SystemData_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20230701.VaultOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VaultOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230701.VaultProperties // Properties of the vault type VaultProperties struct { diff --git a/v2/api/keyvault/v1api20230701/storage/vault_types_gen_test.go b/v2/api/keyvault/v1api20230701/storage/vault_types_gen_test.go index adab612108e..4a3f9c6e588 100644 --- a/v2/api/keyvault/v1api20230701/storage/vault_types_gen_test.go +++ b/v2/api/keyvault/v1api20230701/storage/vault_types_gen_test.go @@ -1019,6 +1019,60 @@ func AddRelatedPropertyGeneratorsForVault(gens map[string]gopter.Gen) { gens["Status"] = Vault_STATUSGenerator() } +func Test_VaultOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VaultOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVaultOperatorSpec runs a test to see if a specific instance of VaultOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VaultOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VaultOperatorSpec instances for property testing - lazily instantiated by VaultOperatorSpecGenerator() +var vaultOperatorSpecGenerator gopter.Gen + +// VaultOperatorSpecGenerator returns a generator of VaultOperatorSpec instances for property testing. +func VaultOperatorSpecGenerator() gopter.Gen { + if vaultOperatorSpecGenerator != nil { + return vaultOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + vaultOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VaultOperatorSpec{}), generators) + + return vaultOperatorSpecGenerator +} + func Test_VaultProperties_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1353,6 +1407,7 @@ func AddIndependentPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForVault_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VaultOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(VaultPropertiesGenerator()) } diff --git a/v2/api/keyvault/v1api20230701/storage/zz_generated.deepcopy.go b/v2/api/keyvault/v1api20230701/storage/zz_generated.deepcopy.go index 8023310c5ee..9bce053474b 100644 --- a/v2/api/keyvault/v1api20230701/storage/zz_generated.deepcopy.go +++ b/v2/api/keyvault/v1api20230701/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -630,6 +631,50 @@ func (in *VaultList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultOperatorSpec) DeepCopyInto(out *VaultOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultOperatorSpec. +func (in *VaultOperatorSpec) DeepCopy() *VaultOperatorSpec { + if in == nil { + return nil + } + out := new(VaultOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VaultProperties) DeepCopyInto(out *VaultProperties) { *out = *in @@ -919,6 +964,11 @@ func (in *Vault_Spec) DeepCopyInto(out *Vault_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VaultOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/keyvault/v1api20230701/structure.txt b/v2/api/keyvault/v1api20230701/structure.txt index e6c84458ac1..53de27dc3d4 100644 --- a/v2/api/keyvault/v1api20230701/structure.txt +++ b/v2/api/keyvault/v1api20230701/structure.txt @@ -5,10 +5,13 @@ APIVersion: Enum (1 value) └── "2023-07-01" Vault: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z0-9-]{3,24}$" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (16 properties) │ │ ├── AccessPolicies: Object (7 properties)[] diff --git a/v2/api/keyvault/v1api20230701/vault_types_gen.go b/v2/api/keyvault/v1api20230701/vault_types_gen.go index 448d12c6e03..62a120daab6 100644 --- a/v2/api/keyvault/v1api20230701/vault_types_gen.go +++ b/v2/api/keyvault/v1api20230701/vault_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (vault *Vault) defaultAzureName() { // defaultImpl applies the code generated defaults to the Vault resource func (vault *Vault) defaultImpl() { vault.defaultAzureName() } +var _ configmaps.Exporter = &Vault{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (vault *Vault) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Vault{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (vault *Vault) SecretDestinationExpressions() []*core.DestinationExpression { + if vault.Spec.OperatorSpec == nil { + return nil + } + return vault.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Vault{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (vault *Vault) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (vault *Vault) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){vault.validateResourceReferences, vault.validateOwnerReference, vault.validateSecretDestinations, vault.validateConfigMapDestinations, vault.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (vault *Vault) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return vault.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return vault.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return vault.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (vault *Vault) validateConfigMapDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (vault *Vault) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&vault.Spec) @@ -257,6 +293,14 @@ func (vault *Vault) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (vault *Vault) validateSecretDestinations() (admission.Warnings, error) { + if vault.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(vault, nil, vault.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (vault *Vault) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Vault) @@ -353,6 +397,10 @@ type Vault_Spec struct { // Location: The supported Azure location where the key vault should be created. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VaultOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -426,6 +474,8 @@ func (vault *Vault_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc vault.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": vault.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -514,6 +564,18 @@ func (vault *Vault_Spec) AssignProperties_From_Vault_Spec(source *storage.Vault_ // Location vault.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VaultOperatorSpec + err := operatorSpec.AssignProperties_From_VaultOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VaultOperatorSpec() to populate field OperatorSpec") + } + vault.OperatorSpec = &operatorSpec + } else { + vault.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -552,6 +614,18 @@ func (vault *Vault_Spec) AssignProperties_To_Vault_Spec(destination *storage.Vau // Location destination.Location = genruntime.ClonePointerToString(vault.Location) + // OperatorSpec + if vault.OperatorSpec != nil { + var operatorSpec storage.VaultOperatorSpec + err := vault.OperatorSpec.AssignProperties_To_VaultOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VaultOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = vault.OriginalVersion() @@ -1040,6 +1114,110 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VaultOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VaultOperatorSpec populates our VaultOperatorSpec from the provided source VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_From_VaultOperatorSpec(source *storage.VaultOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VaultOperatorSpec populates the provided destination VaultOperatorSpec from our VaultOperatorSpec +func (operator *VaultOperatorSpec) AssignProperties_To_VaultOperatorSpec(destination *storage.VaultOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties of the vault type VaultProperties struct { // AccessPolicies: An array of 0 to 1024 identities that have access to the key vault. All identities in the array must use diff --git a/v2/api/keyvault/v1api20230701/vault_types_gen_test.go b/v2/api/keyvault/v1api20230701/vault_types_gen_test.go index 8e91992ff56..b891aa677f4 100644 --- a/v2/api/keyvault/v1api20230701/vault_types_gen_test.go +++ b/v2/api/keyvault/v1api20230701/vault_types_gen_test.go @@ -1835,6 +1835,102 @@ func AddRelatedPropertyGeneratorsForVault(gens map[string]gopter.Gen) { gens["Status"] = Vault_STATUSGenerator() } +func Test_VaultOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VaultOperatorSpec to VaultOperatorSpec via AssignProperties_To_VaultOperatorSpec & AssignProperties_From_VaultOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVaultOperatorSpec tests if a specific instance of VaultOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VaultOperatorSpec + err := copied.AssignProperties_To_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VaultOperatorSpec + err = actual.AssignProperties_From_VaultOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VaultOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VaultOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVaultOperatorSpec, VaultOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVaultOperatorSpec runs a test to see if a specific instance of VaultOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVaultOperatorSpec(subject VaultOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VaultOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VaultOperatorSpec instances for property testing - lazily instantiated by VaultOperatorSpecGenerator() +var vaultOperatorSpecGenerator gopter.Gen + +// VaultOperatorSpecGenerator returns a generator of VaultOperatorSpec instances for property testing. +func VaultOperatorSpecGenerator() gopter.Gen { + if vaultOperatorSpecGenerator != nil { + return vaultOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + vaultOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VaultOperatorSpec{}), generators) + + return vaultOperatorSpecGenerator +} + func Test_VaultProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2344,6 +2440,7 @@ func AddIndependentPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForVault_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVault_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VaultOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(VaultPropertiesGenerator()) } diff --git a/v2/api/keyvault/v1api20230701/zz_generated.deepcopy.go b/v2/api/keyvault/v1api20230701/zz_generated.deepcopy.go index 0db53946765..3f0d7a318e9 100644 --- a/v2/api/keyvault/v1api20230701/zz_generated.deepcopy.go +++ b/v2/api/keyvault/v1api20230701/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230701 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -532,6 +533,43 @@ func (in *VaultList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VaultOperatorSpec) DeepCopyInto(out *VaultOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultOperatorSpec. +func (in *VaultOperatorSpec) DeepCopy() *VaultOperatorSpec { + if in == nil { + return nil + } + out := new(VaultOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VaultProperties) DeepCopyInto(out *VaultProperties) { *out = *in @@ -800,6 +838,11 @@ func (in *Vault_Spec) DeepCopyInto(out *Vault_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VaultOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/kubernetesconfiguration/v1api20230501/extension_types_gen.go b/v2/api/kubernetesconfiguration/v1api20230501/extension_types_gen.go index e30e0d801e2..86743920610 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/extension_types_gen.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/extension_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -97,6 +99,26 @@ func (extension *Extension) defaultAzureName() { // defaultImpl applies the code generated defaults to the Extension resource func (extension *Extension) defaultImpl() { extension.defaultAzureName() } +var _ configmaps.Exporter = &Extension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *Extension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Extension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *Extension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Extension{} // InitializeSpec initializes the spec for this resource from the given status @@ -233,7 +255,7 @@ func (extension *Extension) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (extension *Extension) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateConfigMapDestinations} + return []func() (admission.Warnings, error){extension.validateResourceReferences, extension.validateSecretDestinations, extension.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -248,6 +270,9 @@ func (extension *Extension) updateValidations() []func(old runtime.Object) (admi return extension.validateResourceReferences() }, extension.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return extension.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return extension.validateConfigMapDestinations() }, @@ -259,13 +284,13 @@ func (extension *Extension) validateConfigMapDestinations() (admission.Warnings, if extension.Spec.OperatorSpec == nil { return nil, nil } - if extension.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - extension.Spec.OperatorSpec.ConfigMaps.PrincipalId, + var toValidate []*genruntime.ConfigMapDestination + if extension.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + extension.Spec.OperatorSpec.ConfigMaps.PrincipalId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(extension, toValidate, extension.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -277,6 +302,14 @@ func (extension *Extension) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (extension *Extension) validateSecretDestinations() (admission.Warnings, error) { + if extension.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(extension, nil, extension.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (extension *Extension) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Extension) @@ -2122,13 +2155,37 @@ func (identity *Extension_Properties_AksAssignedIdentity_STATUS) AssignPropertie // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ExtensionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ExtensionOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_ExtensionOperatorSpec populates our ExtensionOperatorSpec from the provided source ExtensionOperatorSpec func (operator *ExtensionOperatorSpec) AssignProperties_From_ExtensionOperatorSpec(source *storage.ExtensionOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ExtensionOperatorConfigMaps @@ -2141,6 +2198,24 @@ func (operator *ExtensionOperatorSpec) AssignProperties_From_ExtensionOperatorSp operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2150,6 +2225,24 @@ func (operator *ExtensionOperatorSpec) AssignProperties_To_ExtensionOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ExtensionOperatorConfigMaps @@ -2162,6 +2255,24 @@ func (operator *ExtensionOperatorSpec) AssignProperties_To_ExtensionOperatorSpec destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen.go b/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen.go index 1a500d158c5..378dac437de 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (configuration *FluxConfiguration) defaultAzureName() { // defaultImpl applies the code generated defaults to the FluxConfiguration resource func (configuration *FluxConfiguration) defaultImpl() { configuration.defaultAzureName() } +var _ configmaps.Exporter = &FluxConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FluxConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FluxConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FluxConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FluxConfiguration{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +231,7 @@ func (configuration *FluxConfiguration) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (configuration *FluxConfiguration) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){configuration.validateResourceReferences, configuration.validateSecretDestinations, configuration.validateConfigMapDestinations, configuration.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -224,12 +246,26 @@ func (configuration *FluxConfiguration) updateValidations() []func(old runtime.O return configuration.validateResourceReferences() }, configuration.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return configuration.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return configuration.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (configuration *FluxConfiguration) validateConfigMapDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (configuration *FluxConfiguration) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&configuration.Spec) @@ -248,6 +284,14 @@ func (configuration *FluxConfiguration) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (configuration *FluxConfiguration) validateSecretDestinations() (admission.Warnings, error) { + if configuration.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(configuration, nil, configuration.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (configuration *FluxConfiguration) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FluxConfiguration) @@ -353,6 +397,10 @@ type FluxConfiguration_Spec struct { // hyphen and period only. Namespace *string `json:"namespace,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FluxConfigurationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. This resource is an @@ -559,6 +607,8 @@ func (configuration *FluxConfiguration_Spec) PopulateFromARM(owner genruntime.Ar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": configuration.Owner = &owner @@ -736,6 +786,18 @@ func (configuration *FluxConfiguration_Spec) AssignProperties_From_FluxConfigura // Namespace configuration.Namespace = genruntime.ClonePointerToString(source.Namespace) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FluxConfigurationOperatorSpec + err := operatorSpec.AssignProperties_From_FluxConfigurationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FluxConfigurationOperatorSpec() to populate field OperatorSpec") + } + configuration.OperatorSpec = &operatorSpec + } else { + configuration.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -858,6 +920,18 @@ func (configuration *FluxConfiguration_Spec) AssignProperties_To_FluxConfigurati // Namespace destination.Namespace = genruntime.ClonePointerToString(configuration.Namespace) + // OperatorSpec + if configuration.OperatorSpec != nil { + var operatorSpec storage.FluxConfigurationOperatorSpec + err := configuration.OperatorSpec.AssignProperties_To_FluxConfigurationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FluxConfigurationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = configuration.OriginalVersion() @@ -2710,6 +2784,110 @@ var fluxComplianceStateDefinition_STATUS_Values = map[string]FluxComplianceState "unknown": FluxComplianceStateDefinition_STATUS_Unknown, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FluxConfigurationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FluxConfigurationOperatorSpec populates our FluxConfigurationOperatorSpec from the provided source FluxConfigurationOperatorSpec +func (operator *FluxConfigurationOperatorSpec) AssignProperties_From_FluxConfigurationOperatorSpec(source *storage.FluxConfigurationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FluxConfigurationOperatorSpec populates the provided destination FluxConfigurationOperatorSpec from our FluxConfigurationOperatorSpec +func (operator *FluxConfigurationOperatorSpec) AssignProperties_To_FluxConfigurationOperatorSpec(destination *storage.FluxConfigurationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Parameters to reconcile to the GitRepository source kind type. type GitRepositoryDefinition struct { // HttpsCACert: Base64-encoded HTTPS certificate authority contents used to access git private git repositories over HTTPS diff --git a/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen_test.go b/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen_test.go index c35e2f85f58..16f811df0b1 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen_test.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/flux_configuration_types_gen_test.go @@ -623,6 +623,103 @@ func AddRelatedPropertyGeneratorsForFluxConfiguration(gens map[string]gopter.Gen gens["Status"] = FluxConfiguration_STATUSGenerator() } +func Test_FluxConfigurationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FluxConfigurationOperatorSpec to FluxConfigurationOperatorSpec via AssignProperties_To_FluxConfigurationOperatorSpec & AssignProperties_From_FluxConfigurationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFluxConfigurationOperatorSpec, FluxConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFluxConfigurationOperatorSpec tests if a specific instance of FluxConfigurationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFluxConfigurationOperatorSpec(subject FluxConfigurationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FluxConfigurationOperatorSpec + err := copied.AssignProperties_To_FluxConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FluxConfigurationOperatorSpec + err = actual.AssignProperties_From_FluxConfigurationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FluxConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FluxConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFluxConfigurationOperatorSpec, FluxConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFluxConfigurationOperatorSpec runs a test to see if a specific instance of FluxConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFluxConfigurationOperatorSpec(subject FluxConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FluxConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FluxConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FluxConfigurationOperatorSpecGenerator() +var fluxConfigurationOperatorSpecGenerator gopter.Gen + +// FluxConfigurationOperatorSpecGenerator returns a generator of FluxConfigurationOperatorSpec instances for property testing. +func FluxConfigurationOperatorSpecGenerator() gopter.Gen { + if fluxConfigurationOperatorSpecGenerator != nil { + return fluxConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fluxConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FluxConfigurationOperatorSpec{}), generators) + + return fluxConfigurationOperatorSpecGenerator +} + func Test_FluxConfiguration_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -901,6 +998,7 @@ func AddRelatedPropertyGeneratorsForFluxConfiguration_Spec(gens map[string]gopte gens["Kustomizations"] = gen.MapOf( gen.AlphaString(), KustomizationDefinitionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FluxConfigurationOperatorSpecGenerator()) } func Test_GitRepositoryDefinition_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/kubernetesconfiguration/v1api20230501/storage/extension_types_gen.go b/v2/api/kubernetesconfiguration/v1api20230501/storage/extension_types_gen.go index 54c3782c08b..feb79800615 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/storage/extension_types_gen.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/storage/extension_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -50,6 +52,26 @@ func (extension *Extension) SetConditions(conditions conditions.Conditions) { extension.Status.Conditions = conditions } +var _ configmaps.Exporter = &Extension{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (extension *Extension) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Extension{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (extension *Extension) SecretDestinationExpressions() []*core.DestinationExpression { + if extension.Spec.OperatorSpec == nil { + return nil + } + return extension.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Extension{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -292,8 +314,10 @@ type Extension_Properties_AksAssignedIdentity_STATUS struct { // Storage version of v1api20230501.ExtensionOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ExtensionOperatorSpec struct { - ConfigMaps *ExtensionOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ExtensionOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20230501.ExtensionStatus_STATUS diff --git a/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen.go b/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen.go index d776bf974b7..abbd29de67a 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (configuration *FluxConfiguration) SetConditions(conditions conditions.Cond configuration.Status.Conditions = conditions } +var _ configmaps.Exporter = &FluxConfiguration{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (configuration *FluxConfiguration) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FluxConfiguration{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (configuration *FluxConfiguration) SecretDestinationExpressions() []*core.DestinationExpression { + if configuration.Spec.OperatorSpec == nil { + return nil + } + return configuration.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FluxConfiguration{} // AzureName returns the Azure name of the resource @@ -149,6 +172,7 @@ type FluxConfiguration_Spec struct { GitRepository *GitRepositoryDefinition `json:"gitRepository,omitempty"` Kustomizations map[string]KustomizationDefinition `json:"kustomizations,omitempty"` Namespace *string `json:"namespace,omitempty"` + OperatorSpec *FluxConfigurationOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -286,6 +310,14 @@ type BucketDefinition_STATUS struct { Url *string `json:"url,omitempty"` } +// Storage version of v1api20230501.FluxConfigurationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FluxConfigurationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230501.GitRepositoryDefinition // Parameters to reconcile to the GitRepository source kind type. type GitRepositoryDefinition struct { diff --git a/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen_test.go b/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen_test.go index 8f64e246919..c2bc8d1e348 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen_test.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/storage/flux_configuration_types_gen_test.go @@ -369,6 +369,61 @@ func AddRelatedPropertyGeneratorsForFluxConfiguration(gens map[string]gopter.Gen gens["Status"] = FluxConfiguration_STATUSGenerator() } +func Test_FluxConfigurationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FluxConfigurationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFluxConfigurationOperatorSpec, FluxConfigurationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFluxConfigurationOperatorSpec runs a test to see if a specific instance of FluxConfigurationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFluxConfigurationOperatorSpec(subject FluxConfigurationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FluxConfigurationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FluxConfigurationOperatorSpec instances for property testing - lazily instantiated by +// FluxConfigurationOperatorSpecGenerator() +var fluxConfigurationOperatorSpecGenerator gopter.Gen + +// FluxConfigurationOperatorSpecGenerator returns a generator of FluxConfigurationOperatorSpec instances for property testing. +func FluxConfigurationOperatorSpecGenerator() gopter.Gen { + if fluxConfigurationOperatorSpecGenerator != nil { + return fluxConfigurationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + fluxConfigurationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FluxConfigurationOperatorSpec{}), generators) + + return fluxConfigurationOperatorSpecGenerator +} + func Test_FluxConfiguration_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -553,6 +608,7 @@ func AddRelatedPropertyGeneratorsForFluxConfiguration_Spec(gens map[string]gopte gens["Kustomizations"] = gen.MapOf( gen.AlphaString(), KustomizationDefinitionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(FluxConfigurationOperatorSpecGenerator()) } func Test_GitRepositoryDefinition_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/kubernetesconfiguration/v1api20230501/storage/structure.txt b/v2/api/kubernetesconfiguration/v1api20230501/storage/structure.txt index aa5b40c945e..85dd8bae1cf 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/storage/structure.txt +++ b/v2/api/kubernetesconfiguration/v1api20230501/storage/structure.txt @@ -16,11 +16,13 @@ Extension: Resource │ ├── Identity: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Type: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── Plan: *Object (6 properties) @@ -125,7 +127,7 @@ Extension: Resource ├── Type: *string └── Version: *string FluxConfiguration: Resource -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AzureBlob: *Object (10 properties) │ │ ├── AccountKey: *genruntime.SecretReference │ │ ├── ContainerName: *string @@ -193,6 +195,10 @@ FluxConfiguration: Resource │ │ ├── TimeoutInSeconds: *int │ │ └── Wait: *bool │ ├── Namespace: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/kubernetesconfiguration/v1api20230501/storage/zz_generated.deepcopy.go b/v2/api/kubernetesconfiguration/v1api20230501/storage/zz_generated.deepcopy.go index 0a3cdff093d..8a861f7e1d4 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/storage/zz_generated.deepcopy.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -467,6 +468,17 @@ func (in *ExtensionOperatorConfigMaps) DeepCopy() *ExtensionOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtensionOperatorSpec) DeepCopyInto(out *ExtensionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ExtensionOperatorConfigMaps) @@ -479,6 +491,17 @@ func (in *ExtensionOperatorSpec) DeepCopyInto(out *ExtensionOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionOperatorSpec. @@ -892,6 +915,50 @@ func (in *FluxConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluxConfigurationOperatorSpec) DeepCopyInto(out *FluxConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluxConfigurationOperatorSpec. +func (in *FluxConfigurationOperatorSpec) DeepCopy() *FluxConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FluxConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluxConfiguration_STATUS) DeepCopyInto(out *FluxConfiguration_STATUS) { *out = *in @@ -1072,6 +1139,11 @@ func (in *FluxConfiguration_Spec) DeepCopyInto(out *FluxConfiguration_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FluxConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) diff --git a/v2/api/kubernetesconfiguration/v1api20230501/structure.txt b/v2/api/kubernetesconfiguration/v1api20230501/structure.txt index 25cb531c398..be5e6ff864c 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/structure.txt +++ b/v2/api/kubernetesconfiguration/v1api20230501/structure.txt @@ -17,9 +17,11 @@ Extension: Resource │ ├── Identity: *Object (1 property) │ │ └── Type: *Enum (1 value) │ │ └── "SystemAssigned" -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── PrincipalId: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── Plan: *Object (5 properties) │ │ ├── Name: *string @@ -132,7 +134,7 @@ Extension: Resource ├── Type: *string └── Version: *string FluxConfiguration: Resource -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureBlob: *Object (9 properties) │ │ ├── AccountKey: *genruntime.SecretReference │ │ ├── ContainerName: *string @@ -191,6 +193,9 @@ FluxConfiguration: Resource │ │ ├── TimeoutInSeconds: *int │ │ └── Wait: *bool │ ├── Namespace: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.ArbitraryOwnerReference │ ├── ReconciliationWaitDuration: *string │ ├── Scope: *Enum (2 values) diff --git a/v2/api/kubernetesconfiguration/v1api20230501/zz_generated.deepcopy.go b/v2/api/kubernetesconfiguration/v1api20230501/zz_generated.deepcopy.go index 7b33aa37399..5478fd366ff 100644 --- a/v2/api/kubernetesconfiguration/v1api20230501/zz_generated.deepcopy.go +++ b/v2/api/kubernetesconfiguration/v1api20230501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -411,11 +412,33 @@ func (in *ExtensionOperatorConfigMaps) DeepCopy() *ExtensionOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExtensionOperatorSpec) DeepCopyInto(out *ExtensionOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ExtensionOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionOperatorSpec. @@ -794,6 +817,43 @@ func (in *FluxConfigurationList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FluxConfigurationOperatorSpec) DeepCopyInto(out *FluxConfigurationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluxConfigurationOperatorSpec. +func (in *FluxConfigurationOperatorSpec) DeepCopy() *FluxConfigurationOperatorSpec { + if in == nil { + return nil + } + out := new(FluxConfigurationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FluxConfiguration_STATUS) DeepCopyInto(out *FluxConfiguration_STATUS) { *out = *in @@ -967,6 +1027,11 @@ func (in *FluxConfiguration_Spec) DeepCopyInto(out *FluxConfiguration_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FluxConfigurationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.ArbitraryOwnerReference) diff --git a/v2/api/machinelearningservices/v1api20210701/storage/structure.txt b/v2/api/machinelearningservices/v1api20210701/storage/structure.txt index 1d9edb7e57a..753f976a051 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/structure.txt +++ b/v2/api/machinelearningservices/v1api20210701/storage/structure.txt @@ -33,8 +33,10 @@ Workspace: Resource │ ├── ImageBuildCompute: *string │ ├── KeyVaultReference: *genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (8 properties) │ │ ├── AppInsightsInstrumentationKey: *genruntime.SecretDestination │ │ ├── ContainerRegistryPassword: *genruntime.SecretDestination @@ -160,7 +162,7 @@ Workspace: Resource └── WorkspaceId: *string WorkspacesCompute: Resource ├── Owner: machinelearningservices/v1api20210701.Workspace -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AzureName: string │ ├── Identity: *Object (3 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -169,6 +171,10 @@ WorkspacesCompute: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (11 properties) @@ -954,10 +960,14 @@ WorkspacesCompute: Resource └── Type: *string WorkspacesConnection: Resource ├── Owner: machinelearningservices/v1api20210701.Workspace -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AuthType: *string │ ├── AzureName: string │ ├── Category: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1087,8 +1097,10 @@ augmentConversionForWorkspaceOperatorSpec: Interface augmentConversionForWorkspace_STATUS: Interface augmentConversionForWorkspace_Spec: Interface augmentConversionForWorkspacesCompute: Interface +augmentConversionForWorkspacesComputeOperatorSpec: Interface augmentConversionForWorkspacesCompute_STATUS: Interface augmentConversionForWorkspacesCompute_Spec: Interface augmentConversionForWorkspacesConnection: Interface +augmentConversionForWorkspacesConnectionOperatorSpec: Interface augmentConversionForWorkspacesConnection_STATUS: Interface augmentConversionForWorkspacesConnection_Spec: Interface diff --git a/v2/api/machinelearningservices/v1api20210701/storage/workspace_types_gen.go b/v2/api/machinelearningservices/v1api20210701/storage/workspace_types_gen.go index ef4851de8c0..f1d5503a7ab 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/workspace_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/workspace_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/machinelearningservices/v1api20240401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (workspace *Workspace) ConvertTo(hub conversion.Hub) error { return workspace.AssignProperties_To_Workspace(destination) } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Workspace{} // AzureName returns the Azure name of the resource @@ -2964,8 +2987,10 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination // Storage version of v1api20210701.WorkspaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type WorkspaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_WorkspaceOperatorSpec populates our WorkspaceOperatorSpec from the provided source WorkspaceOperatorSpec @@ -2973,6 +2998,42 @@ func (operator *WorkspaceOperatorSpec) AssignProperties_From_WorkspaceOperatorSp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret WorkspaceOperatorSecrets @@ -3010,6 +3071,42 @@ func (operator *WorkspaceOperatorSpec) AssignProperties_To_WorkspaceOperatorSpec // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.WorkspaceOperatorSecrets diff --git a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen.go b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen.go index 6b5cef1bdb5..84cbe23f3e8 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/machinelearningservices/v1api20240401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -66,6 +69,26 @@ func (compute *WorkspacesCompute) ConvertTo(hub conversion.Hub) error { return compute.AssignProperties_To_WorkspacesCompute(destination) } +var _ configmaps.Exporter = &WorkspacesCompute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (compute *WorkspacesCompute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesCompute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (compute *WorkspacesCompute) SecretDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesCompute{} // AzureName returns the Azure name of the resource @@ -236,10 +259,11 @@ type augmentConversionForWorkspacesCompute interface { type WorkspacesCompute_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Identity *Identity `json:"identity,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Identity *Identity `json:"identity,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *WorkspacesComputeOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -326,6 +350,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_From_WorkspacesCompute_S // Location compute.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesComputeOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesComputeOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + compute.OperatorSpec = &operatorSpec + } else { + compute.OperatorSpec = nil + } + // OriginalVersion compute.OriginalVersion = source.OriginalVersion @@ -420,6 +456,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_To_WorkspacesCompute_Spe // Location destination.Location = genruntime.ClonePointerToString(compute.Location) + // OperatorSpec + if compute.OperatorSpec != nil { + var operatorSpec storage.WorkspacesComputeOperatorSpec + err := compute.OperatorSpec.AssignProperties_To_WorkspacesComputeOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = compute.OriginalVersion @@ -1352,6 +1400,136 @@ func (compute *Compute_STATUS) AssignProperties_To_Compute_STATUS(destination *s return nil } +// Storage version of v1api20210701.WorkspacesComputeOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesComputeOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesComputeOperatorSpec populates our WorkspacesComputeOperatorSpec from the provided source WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_From_WorkspacesComputeOperatorSpec(source *storage.WorkspacesComputeOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForWorkspacesComputeOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWorkspacesComputeOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesComputeOperatorSpec populates the provided destination WorkspacesComputeOperatorSpec from our WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_To_WorkspacesComputeOperatorSpec(destination *storage.WorkspacesComputeOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForWorkspacesComputeOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWorkspacesComputeOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210701.AKS type AKS struct { ComputeLocation *string `json:"computeLocation,omitempty"` @@ -2036,6 +2214,11 @@ type augmentConversionForCompute_STATUS interface { AssignPropertiesTo(dst *storage.Compute_STATUS) error } +type augmentConversionForWorkspacesComputeOperatorSpec interface { + AssignPropertiesFrom(src *storage.WorkspacesComputeOperatorSpec) error + AssignPropertiesTo(dst *storage.WorkspacesComputeOperatorSpec) error +} + // Storage version of v1api20210701.ComputeInstance type ComputeInstance struct { ComputeLocation *string `json:"computeLocation,omitempty"` diff --git a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen_test.go b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen_test.go index 450def530b8..4f50072b9b1 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_compute_types_gen_test.go @@ -9636,6 +9636,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesCompute(gens map[string]gopter.Gen gens["Status"] = WorkspacesCompute_STATUSGenerator() } +func Test_WorkspacesComputeOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesComputeOperatorSpec to WorkspacesComputeOperatorSpec via AssignProperties_To_WorkspacesComputeOperatorSpec & AssignProperties_From_WorkspacesComputeOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec tests if a specific instance of WorkspacesComputeOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspacesComputeOperatorSpec + err := copied.AssignProperties_To_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesComputeOperatorSpec + err = actual.AssignProperties_From_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesComputeOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesComputeOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesComputeOperatorSpec runs a test to see if a specific instance of WorkspacesComputeOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesComputeOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesComputeOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesComputeOperatorSpecGenerator() +var workspacesComputeOperatorSpecGenerator gopter.Gen + +// WorkspacesComputeOperatorSpecGenerator returns a generator of WorkspacesComputeOperatorSpec instances for property testing. +func WorkspacesComputeOperatorSpecGenerator() gopter.Gen { + if workspacesComputeOperatorSpecGenerator != nil { + return workspacesComputeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesComputeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesComputeOperatorSpec{}), generators) + + return workspacesComputeOperatorSpecGenerator +} + func Test_WorkspacesCompute_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -9882,6 +9979,7 @@ func AddIndependentPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]g // AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(IdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesComputeOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(ComputeGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) gens["SystemData"] = gen.PtrOf(SystemDataGenerator()) diff --git a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen.go b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen.go index a952cf6ab91..9f195696bc8 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/machinelearningservices/v1api20240401/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (connection *WorkspacesConnection) ConvertTo(hub conversion.Hub) error { return connection.AssignProperties_To_WorkspacesConnection(destination) } +var _ configmaps.Exporter = &WorkspacesConnection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (connection *WorkspacesConnection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesConnection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (connection *WorkspacesConnection) SecretDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesConnection{} // AzureName returns the Azure name of the resource @@ -237,9 +260,10 @@ type WorkspacesConnection_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Category *string `json:"category,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Category *string `json:"category,omitempty"` + OperatorSpec *WorkspacesConnectionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -336,6 +360,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_From_WorkspacesCon connection.Category = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesConnectionOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesConnectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + connection.OperatorSpec = &operatorSpec + } else { + connection.OperatorSpec = nil + } + // OriginalVersion connection.OriginalVersion = source.OriginalVersion @@ -435,6 +471,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_To_WorkspacesConne propertyBag.Remove("Category") } + // OperatorSpec + if connection.OperatorSpec != nil { + var operatorSpec storage.WorkspacesConnectionOperatorSpec + err := connection.OperatorSpec.AssignProperties_To_WorkspacesConnectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = connection.OriginalVersion @@ -788,6 +836,141 @@ type augmentConversionForWorkspacesConnection_STATUS interface { AssignPropertiesTo(dst *storage.WorkspacesConnection_STATUS) error } +// Storage version of v1api20210701.WorkspacesConnectionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesConnectionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesConnectionOperatorSpec populates our WorkspacesConnectionOperatorSpec from the provided source WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_From_WorkspacesConnectionOperatorSpec(source *storage.WorkspacesConnectionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForWorkspacesConnectionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWorkspacesConnectionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesConnectionOperatorSpec populates the provided destination WorkspacesConnectionOperatorSpec from our WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_To_WorkspacesConnectionOperatorSpec(destination *storage.WorkspacesConnectionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForWorkspacesConnectionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForWorkspacesConnectionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForWorkspacesConnectionOperatorSpec interface { + AssignPropertiesFrom(src *storage.WorkspacesConnectionOperatorSpec) error + AssignPropertiesTo(dst *storage.WorkspacesConnectionOperatorSpec) error +} + func init() { SchemeBuilder.Register(&WorkspacesConnection{}, &WorkspacesConnectionList{}) } diff --git a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen_test.go b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen_test.go index a403b827fff..95639fbabfb 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/workspaces_connection_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesConnection(gens map[string]gopter. gens["Status"] = WorkspacesConnection_STATUSGenerator() } +func Test_WorkspacesConnectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesConnectionOperatorSpec to WorkspacesConnectionOperatorSpec via AssignProperties_To_WorkspacesConnectionOperatorSpec & AssignProperties_From_WorkspacesConnectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec tests if a specific instance of WorkspacesConnectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspacesConnectionOperatorSpec + err := copied.AssignProperties_To_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesConnectionOperatorSpec + err = actual.AssignProperties_From_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesConnectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesConnectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesConnectionOperatorSpec runs a test to see if a specific instance of WorkspacesConnectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesConnectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesConnectionOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesConnectionOperatorSpecGenerator() +var workspacesConnectionOperatorSpecGenerator gopter.Gen + +// WorkspacesConnectionOperatorSpecGenerator returns a generator of WorkspacesConnectionOperatorSpec instances for property testing. +func WorkspacesConnectionOperatorSpecGenerator() gopter.Gen { + if workspacesConnectionOperatorSpecGenerator != nil { + return workspacesConnectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesConnectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnectionOperatorSpec{}), generators) + + return workspacesConnectionOperatorSpecGenerator +} + func Test_WorkspacesConnection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForWorkspacesConnection_Spec(subject WorkspacesConn var workspacesConnection_SpecGenerator gopter.Gen // WorkspacesConnection_SpecGenerator returns a generator of WorkspacesConnection_Spec instances for property testing. +// We first initialize workspacesConnection_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func WorkspacesConnection_SpecGenerator() gopter.Gen { if workspacesConnection_SpecGenerator != nil { return workspacesConnection_SpecGenerator @@ -370,6 +470,12 @@ func WorkspacesConnection_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(generators) workspacesConnection_SpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnection_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(generators) + AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(generators) + workspacesConnection_SpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnection_Spec{}), generators) + return workspacesConnection_SpecGenerator } @@ -383,3 +489,8 @@ func AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(gens map[strin gens["Value"] = gen.PtrOf(gen.AlphaString()) gens["ValueFormat"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(WorkspacesConnectionOperatorSpecGenerator()) +} diff --git a/v2/api/machinelearningservices/v1api20210701/storage/zz_generated.deepcopy.go b/v2/api/machinelearningservices/v1api20210701/storage/zz_generated.deepcopy.go index 10f8a41e905..10ad64718e4 100644 --- a/v2/api/machinelearningservices/v1api20210701/storage/zz_generated.deepcopy.go +++ b/v2/api/machinelearningservices/v1api20210701/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -4926,6 +4927,17 @@ func (in *WorkspaceOperatorSecrets) DeepCopy() *WorkspaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -4933,6 +4945,17 @@ func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(WorkspaceOperatorSecrets) @@ -5340,6 +5363,50 @@ func (in *WorkspacesComputeList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesComputeOperatorSpec) DeepCopyInto(out *WorkspacesComputeOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesComputeOperatorSpec. +func (in *WorkspacesComputeOperatorSpec) DeepCopy() *WorkspacesComputeOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesComputeOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesCompute_STATUS) DeepCopyInto(out *WorkspacesCompute_STATUS) { *out = *in @@ -5429,6 +5496,11 @@ func (in *WorkspacesCompute_Spec) DeepCopyInto(out *WorkspacesCompute_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesComputeOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5534,6 +5606,50 @@ func (in *WorkspacesConnectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesConnectionOperatorSpec) DeepCopyInto(out *WorkspacesConnectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesConnectionOperatorSpec. +func (in *WorkspacesConnectionOperatorSpec) DeepCopy() *WorkspacesConnectionOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesConnectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_STATUS) DeepCopyInto(out *WorkspacesConnection_STATUS) { *out = *in @@ -5616,6 +5732,11 @@ func (in *WorkspacesConnection_Spec) DeepCopyInto(out *WorkspacesConnection_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesConnectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/machinelearningservices/v1api20210701/structure.txt b/v2/api/machinelearningservices/v1api20210701/structure.txt index 8e1762410f5..fce4796b3b1 100644 --- a/v2/api/machinelearningservices/v1api20210701/structure.txt +++ b/v2/api/machinelearningservices/v1api20210701/structure.txt @@ -32,7 +32,9 @@ Workspace: Resource │ ├── ImageBuildCompute: *string │ ├── KeyVaultReference: *genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (7 properties) │ │ ├── AppInsightsInstrumentationKey: *genruntime.SecretDestination │ │ ├── ContainerRegistryPassword: *genruntime.SecretDestination @@ -179,7 +181,7 @@ Workspace: Resource └── WorkspaceId: *string WorkspacesCompute: Resource ├── Owner: Workspace -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── Identity: *Object (2 properties) │ │ ├── Type: *Enum (4 values) @@ -190,6 +192,9 @@ WorkspacesCompute: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (10 properties) │ │ ├── AKS: *Object (6 properties) @@ -1005,10 +1010,13 @@ WorkspacesCompute: Resource └── Type: *string WorkspacesConnection: Resource ├── Owner: Workspace -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AuthType: *string │ ├── AzureName: string │ ├── Category: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Target: *string │ ├── Value: *string diff --git a/v2/api/machinelearningservices/v1api20210701/workspace_types_gen.go b/v2/api/machinelearningservices/v1api20210701/workspace_types_gen.go index 70b7d7e8700..c61f13388c4 100644 --- a/v2/api/machinelearningservices/v1api20210701/workspace_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/workspace_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (workspace *Workspace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Workspace resource func (workspace *Workspace) defaultImpl() { workspace.defaultAzureName() } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Workspace{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (workspace *Workspace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (workspace *Workspace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations} + return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations, workspace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (workspace *Workspace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return workspace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (workspace *Workspace) validateConfigMapDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,19 +289,19 @@ func (workspace *Workspace) validateSecretDestinations() (admission.Warnings, er if workspace.Spec.OperatorSpec == nil { return nil, nil } - if workspace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - workspace.Spec.OperatorSpec.Secrets.AppInsightsInstrumentationKey, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword2, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryUserName, - workspace.Spec.OperatorSpec.Secrets.PrimaryNotebookAccessKey, - workspace.Spec.OperatorSpec.Secrets.SecondaryNotebookAccessKey, - workspace.Spec.OperatorSpec.Secrets.UserStorageKey, + var toValidate []*genruntime.SecretDestination + if workspace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + workspace.Spec.OperatorSpec.Secrets.AppInsightsInstrumentationKey, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword2, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryUserName, + workspace.Spec.OperatorSpec.Secrets.PrimaryNotebookAccessKey, + workspace.Spec.OperatorSpec.Secrets.SecondaryNotebookAccessKey, + workspace.Spec.OperatorSpec.Secrets.UserStorageKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(workspace, toValidate, workspace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -3992,6 +4025,12 @@ func (data *SystemData_STATUS) AssignProperties_To_SystemData_STATUS(destination // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type WorkspaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` } @@ -3999,6 +4038,42 @@ type WorkspaceOperatorSpec struct { // AssignProperties_From_WorkspaceOperatorSpec populates our WorkspaceOperatorSpec from the provided source WorkspaceOperatorSpec func (operator *WorkspaceOperatorSpec) AssignProperties_From_WorkspaceOperatorSpec(source *storage.WorkspaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret WorkspaceOperatorSecrets @@ -4020,6 +4095,42 @@ func (operator *WorkspaceOperatorSpec) AssignProperties_To_WorkspaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.WorkspaceOperatorSecrets diff --git a/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen.go b/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen.go index b87282daf53..99496e1a108 100644 --- a/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +109,26 @@ func (compute *WorkspacesCompute) defaultAzureName() { // defaultImpl applies the code generated defaults to the WorkspacesCompute resource func (compute *WorkspacesCompute) defaultImpl() { compute.defaultAzureName() } +var _ configmaps.Exporter = &WorkspacesCompute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (compute *WorkspacesCompute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesCompute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (compute *WorkspacesCompute) SecretDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesCompute{} // AzureName returns the Azure name of the resource @@ -213,7 +236,7 @@ func (compute *WorkspacesCompute) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (compute *WorkspacesCompute) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){compute.validateResourceReferences, compute.validateOwnerReference} + return []func() (admission.Warnings, error){compute.validateResourceReferences, compute.validateOwnerReference, compute.validateSecretDestinations, compute.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +254,21 @@ func (compute *WorkspacesCompute) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return compute.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return compute.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return compute.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (compute *WorkspacesCompute) validateConfigMapDestinations() (admission.Warnings, error) { + if compute.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(compute, nil, compute.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -248,6 +285,14 @@ func (compute *WorkspacesCompute) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (compute *WorkspacesCompute) validateSecretDestinations() (admission.Warnings, error) { + if compute.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(compute, nil, compute.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (compute *WorkspacesCompute) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WorkspacesCompute) @@ -340,6 +385,10 @@ type WorkspacesCompute_Spec struct { // Location: Specifies the location of the resource. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspacesComputeOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -459,6 +508,8 @@ func (compute *WorkspacesCompute_Spec) PopulateFromARM(owner genruntime.Arbitrar compute.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": compute.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -581,6 +632,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_From_WorkspacesCompute_S // Location compute.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesComputeOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesComputeOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + compute.OperatorSpec = &operatorSpec + } else { + compute.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -655,6 +718,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_To_WorkspacesCompute_Spe // Location destination.Location = genruntime.ClonePointerToString(compute.Location) + // OperatorSpec + if compute.OperatorSpec != nil { + var operatorSpec storage.WorkspacesComputeOperatorSpec + err := compute.OperatorSpec.AssignProperties_To_WorkspacesComputeOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = compute.OriginalVersion() @@ -2013,6 +2088,110 @@ func (compute *Compute_STATUS) AssignProperties_To_Compute_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesComputeOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesComputeOperatorSpec populates our WorkspacesComputeOperatorSpec from the provided source WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_From_WorkspacesComputeOperatorSpec(source *storage.WorkspacesComputeOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesComputeOperatorSpec populates the provided destination WorkspacesComputeOperatorSpec from our WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_To_WorkspacesComputeOperatorSpec(destination *storage.WorkspacesComputeOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AKS struct { // ComputeLocation: Location for the underlying compute ComputeLocation *string `json:"computeLocation,omitempty"` diff --git a/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen_test.go b/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen_test.go index 85b6b20776c..7dcb264d648 100644 --- a/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20210701/workspaces_compute_types_gen_test.go @@ -9736,6 +9736,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesCompute(gens map[string]gopter.Gen gens["Status"] = WorkspacesCompute_STATUSGenerator() } +func Test_WorkspacesComputeOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesComputeOperatorSpec to WorkspacesComputeOperatorSpec via AssignProperties_To_WorkspacesComputeOperatorSpec & AssignProperties_From_WorkspacesComputeOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec tests if a specific instance of WorkspacesComputeOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210701s.WorkspacesComputeOperatorSpec + err := copied.AssignProperties_To_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesComputeOperatorSpec + err = actual.AssignProperties_From_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesComputeOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesComputeOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesComputeOperatorSpec runs a test to see if a specific instance of WorkspacesComputeOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesComputeOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesComputeOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesComputeOperatorSpecGenerator() +var workspacesComputeOperatorSpecGenerator gopter.Gen + +// WorkspacesComputeOperatorSpecGenerator returns a generator of WorkspacesComputeOperatorSpec instances for property testing. +func WorkspacesComputeOperatorSpecGenerator() gopter.Gen { + if workspacesComputeOperatorSpecGenerator != nil { + return workspacesComputeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesComputeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesComputeOperatorSpec{}), generators) + + return workspacesComputeOperatorSpecGenerator +} + func Test_WorkspacesCompute_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -9981,6 +10078,7 @@ func AddIndependentPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]g // AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(IdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesComputeOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(ComputeGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) gens["SystemData"] = gen.PtrOf(SystemDataGenerator()) diff --git a/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen.go b/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen.go index a12a9d9027a..5d2eadd834f 100644 --- a/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen.go +++ b/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (connection *WorkspacesConnection) defaultAzureName() { // defaultImpl applies the code generated defaults to the WorkspacesConnection resource func (connection *WorkspacesConnection) defaultImpl() { connection.defaultAzureName() } +var _ configmaps.Exporter = &WorkspacesConnection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (connection *WorkspacesConnection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesConnection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (connection *WorkspacesConnection) SecretDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesConnection{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (connection *WorkspacesConnection) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (connection *WorkspacesConnection) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){connection.validateResourceReferences, connection.validateOwnerReference} + return []func() (admission.Warnings, error){connection.validateResourceReferences, connection.validateOwnerReference, connection.validateSecretDestinations, connection.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (connection *WorkspacesConnection) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return connection.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return connection.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return connection.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (connection *WorkspacesConnection) validateConfigMapDestinations() (admission.Warnings, error) { + if connection.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(connection, nil, connection.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (connection *WorkspacesConnection) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (connection *WorkspacesConnection) validateSecretDestinations() (admission.Warnings, error) { + if connection.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(connection, nil, connection.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (connection *WorkspacesConnection) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WorkspacesConnection) @@ -339,6 +384,10 @@ type WorkspacesConnection_Spec struct { // Category: Category of the workspace connection. Category *string `json:"category,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspacesConnectionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -433,6 +482,8 @@ func (connection *WorkspacesConnection_Spec) PopulateFromARM(owner genruntime.Ar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": connection.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -534,6 +585,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_From_WorkspacesCon // Category connection.Category = genruntime.ClonePointerToString(source.Category) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesConnectionOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesConnectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + connection.OperatorSpec = &operatorSpec + } else { + connection.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -575,6 +638,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_To_WorkspacesConne // Category destination.Category = genruntime.ClonePointerToString(connection.Category) + // OperatorSpec + if connection.OperatorSpec != nil { + var operatorSpec storage.WorkspacesConnectionOperatorSpec + err := connection.OperatorSpec.AssignProperties_To_WorkspacesConnectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = connection.OriginalVersion() @@ -892,6 +967,110 @@ var workspaceConnectionProps_ValueFormat_STATUS_Values = map[string]WorkspaceCon "json": WorkspaceConnectionProps_ValueFormat_STATUS_JSON, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesConnectionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesConnectionOperatorSpec populates our WorkspacesConnectionOperatorSpec from the provided source WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_From_WorkspacesConnectionOperatorSpec(source *storage.WorkspacesConnectionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesConnectionOperatorSpec populates the provided destination WorkspacesConnectionOperatorSpec from our WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_To_WorkspacesConnectionOperatorSpec(destination *storage.WorkspacesConnectionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&WorkspacesConnection{}, &WorkspacesConnectionList{}) } diff --git a/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen_test.go b/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen_test.go index 14ae916c49b..921525dee7f 100644 --- a/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20210701/workspaces_connection_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesConnection(gens map[string]gopter. gens["Status"] = WorkspacesConnection_STATUSGenerator() } +func Test_WorkspacesConnectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesConnectionOperatorSpec to WorkspacesConnectionOperatorSpec via AssignProperties_To_WorkspacesConnectionOperatorSpec & AssignProperties_From_WorkspacesConnectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec tests if a specific instance of WorkspacesConnectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210701s.WorkspacesConnectionOperatorSpec + err := copied.AssignProperties_To_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesConnectionOperatorSpec + err = actual.AssignProperties_From_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesConnectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesConnectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesConnectionOperatorSpec runs a test to see if a specific instance of WorkspacesConnectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesConnectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesConnectionOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesConnectionOperatorSpecGenerator() +var workspacesConnectionOperatorSpecGenerator gopter.Gen + +// WorkspacesConnectionOperatorSpecGenerator returns a generator of WorkspacesConnectionOperatorSpec instances for property testing. +func WorkspacesConnectionOperatorSpecGenerator() gopter.Gen { + if workspacesConnectionOperatorSpecGenerator != nil { + return workspacesConnectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesConnectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnectionOperatorSpec{}), generators) + + return workspacesConnectionOperatorSpecGenerator +} + func Test_WorkspacesConnection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -362,6 +459,9 @@ func RunJSONSerializationTestForWorkspacesConnection_Spec(subject WorkspacesConn var workspacesConnection_SpecGenerator gopter.Gen // WorkspacesConnection_SpecGenerator returns a generator of WorkspacesConnection_Spec instances for property testing. +// We first initialize workspacesConnection_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func WorkspacesConnection_SpecGenerator() gopter.Gen { if workspacesConnection_SpecGenerator != nil { return workspacesConnection_SpecGenerator @@ -371,6 +471,12 @@ func WorkspacesConnection_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(generators) workspacesConnection_SpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnection_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(generators) + AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(generators) + workspacesConnection_SpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnection_Spec{}), generators) + return workspacesConnection_SpecGenerator } @@ -383,3 +489,8 @@ func AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(gens map[strin gens["Value"] = gen.PtrOf(gen.AlphaString()) gens["ValueFormat"] = gen.PtrOf(gen.OneConstOf(WorkspaceConnectionProps_ValueFormat_JSON)) } + +// AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(WorkspacesConnectionOperatorSpecGenerator()) +} diff --git a/v2/api/machinelearningservices/v1api20210701/zz_generated.deepcopy.go b/v2/api/machinelearningservices/v1api20210701/zz_generated.deepcopy.go index d0dd056e3a9..12e236a1552 100644 --- a/v2/api/machinelearningservices/v1api20210701/zz_generated.deepcopy.go +++ b/v2/api/machinelearningservices/v1api20210701/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210701 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -4168,6 +4169,28 @@ func (in *WorkspaceOperatorSecrets) DeepCopy() *WorkspaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(WorkspaceOperatorSecrets) @@ -4561,6 +4584,43 @@ func (in *WorkspacesComputeList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesComputeOperatorSpec) DeepCopyInto(out *WorkspacesComputeOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesComputeOperatorSpec. +func (in *WorkspacesComputeOperatorSpec) DeepCopy() *WorkspacesComputeOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesComputeOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesCompute_STATUS) DeepCopyInto(out *WorkspacesCompute_STATUS) { *out = *in @@ -4643,6 +4703,11 @@ func (in *WorkspacesCompute_Spec) DeepCopyInto(out *WorkspacesCompute_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesComputeOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4741,6 +4806,43 @@ func (in *WorkspacesConnectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesConnectionOperatorSpec) DeepCopyInto(out *WorkspacesConnectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesConnectionOperatorSpec. +func (in *WorkspacesConnectionOperatorSpec) DeepCopy() *WorkspacesConnectionOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesConnectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_STATUS) DeepCopyInto(out *WorkspacesConnection_STATUS) { *out = *in @@ -4816,6 +4918,11 @@ func (in *WorkspacesConnection_Spec) DeepCopyInto(out *WorkspacesConnection_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesConnectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/machinelearningservices/v1api20240401/registry_types_gen.go b/v2/api/machinelearningservices/v1api20240401/registry_types_gen.go index 57de6cbcff7..8ab0ee29f48 100644 --- a/v2/api/machinelearningservices/v1api20240401/registry_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/registry_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (registry *Registry) defaultAzureName() { // defaultImpl applies the code generated defaults to the Registry resource func (registry *Registry) defaultImpl() { registry.defaultAzureName() } +var _ configmaps.Exporter = &Registry{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (registry *Registry) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Registry{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (registry *Registry) SecretDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Registry{} // InitializeSpec initializes the spec for this resource from the given status @@ -236,7 +258,7 @@ func (registry *Registry) ValidateUpdate(old runtime.Object) (admission.Warnings // createValidations validates the creation of the resource func (registry *Registry) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){registry.validateResourceReferences, registry.validateOwnerReference, registry.validateConfigMapDestinations} + return []func() (admission.Warnings, error){registry.validateResourceReferences, registry.validateOwnerReference, registry.validateSecretDestinations, registry.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -254,6 +276,9 @@ func (registry *Registry) updateValidations() []func(old runtime.Object) (admiss func(old runtime.Object) (admission.Warnings, error) { return registry.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return registry.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return registry.validateConfigMapDestinations() }, @@ -265,14 +290,14 @@ func (registry *Registry) validateConfigMapDestinations() (admission.Warnings, e if registry.Spec.OperatorSpec == nil { return nil, nil } - if registry.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - registry.Spec.OperatorSpec.ConfigMaps.DiscoveryUrl, - registry.Spec.OperatorSpec.ConfigMaps.MlFlowRegistryUri, + var toValidate []*genruntime.ConfigMapDestination + if registry.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + registry.Spec.OperatorSpec.ConfigMaps.DiscoveryUrl, + registry.Spec.OperatorSpec.ConfigMaps.MlFlowRegistryUri, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(registry, toValidate, registry.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -289,6 +314,14 @@ func (registry *Registry) validateResourceReferences() (admission.Warnings, erro return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (registry *Registry) validateSecretDestinations() (admission.Warnings, error) { + if registry.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(registry, nil, registry.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (registry *Registry) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Registry) @@ -2110,13 +2143,37 @@ func (identity *ManagedServiceIdentity_STATUS) AssignProperties_To_ManagedServic // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RegistryOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *RegistryOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_RegistryOperatorSpec populates our RegistryOperatorSpec from the provided source RegistryOperatorSpec func (operator *RegistryOperatorSpec) AssignProperties_From_RegistryOperatorSpec(source *storage.RegistryOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap RegistryOperatorConfigMaps @@ -2129,6 +2186,24 @@ func (operator *RegistryOperatorSpec) AssignProperties_From_RegistryOperatorSpec operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2138,6 +2213,24 @@ func (operator *RegistryOperatorSpec) AssignProperties_To_RegistryOperatorSpec(d // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.RegistryOperatorConfigMaps @@ -2150,6 +2243,24 @@ func (operator *RegistryOperatorSpec) AssignProperties_To_RegistryOperatorSpec(d destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/machinelearningservices/v1api20240401/storage/registry_types_gen.go b/v2/api/machinelearningservices/v1api20240401/storage/registry_types_gen.go index c39d8d8b6db..cd6a63509d9 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/registry_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/registry_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (registry *Registry) SetConditions(conditions conditions.Conditions) { registry.Status.Conditions = conditions } +var _ configmaps.Exporter = &Registry{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (registry *Registry) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Registry{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (registry *Registry) SecretDestinationExpressions() []*core.DestinationExpression { + if registry.Spec.OperatorSpec == nil { + return nil + } + return registry.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Registry{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -301,8 +323,10 @@ type ManagedServiceIdentity_STATUS struct { // Storage version of v1api20240401.RegistryOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type RegistryOperatorSpec struct { - ConfigMaps *RegistryOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *RegistryOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20240401.RegistryPrivateEndpointConnection diff --git a/v2/api/machinelearningservices/v1api20240401/storage/structure.txt b/v2/api/machinelearningservices/v1api20240401/storage/structure.txt index 83485c92c6b..a453c5d1e59 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/structure.txt +++ b/v2/api/machinelearningservices/v1api20240401/storage/structure.txt @@ -21,12 +21,14 @@ Registry: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── ResourceReference: *genruntime.ResourceReference │ ├── MlFlowRegistryUri: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── DiscoveryUrl: *genruntime.ConfigMapDestination │ │ │ ├── MlFlowRegistryUri: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -247,8 +249,10 @@ Workspace: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── SparkReady: *bool │ │ └── Status: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (8 properties) │ │ ├── AppInsightsInstrumentationKey: *genruntime.SecretDestination │ │ ├── ContainerRegistryPassword: *genruntime.SecretDestination @@ -439,7 +443,7 @@ Workspace: Resource └── WorkspaceId: *string WorkspacesCompute: Resource ├── Owner: machinelearningservices/v1api20240401.Workspace -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Identity: *Object (3 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -448,6 +452,10 @@ WorkspacesCompute: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (11 properties) @@ -1414,8 +1422,12 @@ WorkspacesCompute: Resource └── Type: *string WorkspacesConnection: Resource ├── Owner: machinelearningservices/v1api20240401.Workspace -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (13 properties) diff --git a/v2/api/machinelearningservices/v1api20240401/storage/workspace_types_gen.go b/v2/api/machinelearningservices/v1api20240401/storage/workspace_types_gen.go index 5895b2393c3..34b74b10ca4 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/workspace_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/workspace_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (workspace *Workspace) SetConditions(conditions conditions.Conditions) { workspace.Status.Conditions = conditions } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Workspace{} // AzureName returns the Azure name of the resource @@ -420,8 +443,10 @@ type WorkspaceHubConfig_STATUS struct { // Storage version of v1api20240401.WorkspaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type WorkspaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20240401.ComputeRuntimeDto diff --git a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen.go b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen.go index c3f8eaf2c6b..59b302e168f 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (compute *WorkspacesCompute) SetConditions(conditions conditions.Conditions compute.Status.Conditions = conditions } +var _ configmaps.Exporter = &WorkspacesCompute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (compute *WorkspacesCompute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesCompute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (compute *WorkspacesCompute) SecretDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesCompute{} // AzureName returns the Azure name of the resource @@ -143,10 +166,11 @@ type WorkspacesComputeList struct { type WorkspacesCompute_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Identity *ManagedServiceIdentity `json:"identity,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Identity *ManagedServiceIdentity `json:"identity,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *WorkspacesComputeOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -244,6 +268,14 @@ type Compute_STATUS struct { VirtualMachine *VirtualMachine_STATUS `json:"virtualMachine,omitempty"` } +// Storage version of v1api20240401.WorkspacesComputeOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesComputeOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240401.AKS type AKS struct { ComputeLocation *string `json:"computeLocation,omitempty"` diff --git a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen_test.go b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen_test.go index 46e3edb4a30..35c8aa35c90 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_compute_types_gen_test.go @@ -8425,6 +8425,61 @@ func AddRelatedPropertyGeneratorsForWorkspacesCompute(gens map[string]gopter.Gen gens["Status"] = WorkspacesCompute_STATUSGenerator() } +func Test_WorkspacesComputeOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesComputeOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesComputeOperatorSpec runs a test to see if a specific instance of WorkspacesComputeOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesComputeOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesComputeOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesComputeOperatorSpecGenerator() +var workspacesComputeOperatorSpecGenerator gopter.Gen + +// WorkspacesComputeOperatorSpecGenerator returns a generator of WorkspacesComputeOperatorSpec instances for property testing. +func WorkspacesComputeOperatorSpecGenerator() gopter.Gen { + if workspacesComputeOperatorSpecGenerator != nil { + return workspacesComputeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesComputeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesComputeOperatorSpec{}), generators) + + return workspacesComputeOperatorSpecGenerator +} + func Test_WorkspacesCompute_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -8587,6 +8642,7 @@ func AddIndependentPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]g // AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesComputeOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(ComputeGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen.go b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen.go index f75bc295801..2c5ecece457 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (connection *WorkspacesConnection) SetConditions(conditions conditions.Cond connection.Status.Conditions = conditions } +var _ configmaps.Exporter = &WorkspacesConnection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (connection *WorkspacesConnection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesConnection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (connection *WorkspacesConnection) SecretDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesConnection{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type WorkspacesConnectionList struct { type WorkspacesConnection_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *WorkspacesConnectionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -239,6 +263,14 @@ type WorkspaceConnectionPropertiesV2_STATUS struct { UsernamePassword *UsernamePasswordAuthTypeWorkspaceConnectionProperties_STATUS `json:"usernamePassword,omitempty"` } +// Storage version of v1api20240401.WorkspacesConnectionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesConnectionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240401.AADAuthTypeWorkspaceConnectionProperties type AADAuthTypeWorkspaceConnectionProperties struct { AuthType *string `json:"authType,omitempty"` diff --git a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen_test.go b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen_test.go index 291658e6c97..3fc36361d19 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/workspaces_connection_types_gen_test.go @@ -3466,6 +3466,61 @@ func AddRelatedPropertyGeneratorsForWorkspacesConnection(gens map[string]gopter. gens["Status"] = WorkspacesConnection_STATUSGenerator() } +func Test_WorkspacesConnectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesConnectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesConnectionOperatorSpec runs a test to see if a specific instance of WorkspacesConnectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesConnectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesConnectionOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesConnectionOperatorSpecGenerator() +var workspacesConnectionOperatorSpecGenerator gopter.Gen + +// WorkspacesConnectionOperatorSpecGenerator returns a generator of WorkspacesConnectionOperatorSpec instances for property testing. +func WorkspacesConnectionOperatorSpecGenerator() gopter.Gen { + if workspacesConnectionOperatorSpecGenerator != nil { + return workspacesConnectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesConnectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnectionOperatorSpec{}), generators) + + return workspacesConnectionOperatorSpecGenerator +} + func Test_WorkspacesConnection_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3617,5 +3672,6 @@ func AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(gens map[strin // AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(WorkspacesConnectionOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(WorkspaceConnectionPropertiesV2Generator()) } diff --git a/v2/api/machinelearningservices/v1api20240401/storage/zz_generated.deepcopy.go b/v2/api/machinelearningservices/v1api20240401/storage/zz_generated.deepcopy.go index e8c3be1836d..a90a1f25892 100644 --- a/v2/api/machinelearningservices/v1api20240401/storage/zz_generated.deepcopy.go +++ b/v2/api/machinelearningservices/v1api20240401/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -6872,6 +6873,17 @@ func (in *RegistryOperatorConfigMaps) DeepCopy() *RegistryOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RegistryOperatorSpec) DeepCopyInto(out *RegistryOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(RegistryOperatorConfigMaps) @@ -6884,6 +6896,17 @@ func (in *RegistryOperatorSpec) DeepCopyInto(out *RegistryOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryOperatorSpec. @@ -11151,6 +11174,17 @@ func (in *WorkspaceOperatorSecrets) DeepCopy() *WorkspaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -11158,6 +11192,17 @@ func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(WorkspaceOperatorSecrets) @@ -11650,6 +11695,50 @@ func (in *WorkspacesComputeList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesComputeOperatorSpec) DeepCopyInto(out *WorkspacesComputeOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesComputeOperatorSpec. +func (in *WorkspacesComputeOperatorSpec) DeepCopy() *WorkspacesComputeOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesComputeOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesCompute_STATUS) DeepCopyInto(out *WorkspacesCompute_STATUS) { *out = *in @@ -11739,6 +11828,11 @@ func (in *WorkspacesCompute_Spec) DeepCopyInto(out *WorkspacesCompute_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesComputeOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -11839,6 +11933,50 @@ func (in *WorkspacesConnectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesConnectionOperatorSpec) DeepCopyInto(out *WorkspacesConnectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesConnectionOperatorSpec. +func (in *WorkspacesConnectionOperatorSpec) DeepCopy() *WorkspacesConnectionOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesConnectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_STATUS) DeepCopyInto(out *WorkspacesConnection_STATUS) { *out = *in @@ -11896,6 +12034,11 @@ func (in *WorkspacesConnection_STATUS) DeepCopy() *WorkspacesConnection_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_Spec) DeepCopyInto(out *WorkspacesConnection_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesConnectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/machinelearningservices/v1api20240401/structure.txt b/v2/api/machinelearningservices/v1api20240401/structure.txt index ffa028d8d46..274b40dd148 100644 --- a/v2/api/machinelearningservices/v1api20240401/structure.txt +++ b/v2/api/machinelearningservices/v1api20240401/structure.txt @@ -23,10 +23,12 @@ Registry: Resource │ ├── ManagedResourceGroup: *Object (1 property) │ │ └── ResourceReference: *genruntime.ResourceReference │ ├── MlFlowRegistryUri: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (2 properties) -│ │ ├── DiscoveryUrl: *genruntime.ConfigMapDestination -│ │ └── MlFlowRegistryUri: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (2 properties) +│ │ │ ├── DiscoveryUrl: *genruntime.ConfigMapDestination +│ │ │ └── MlFlowRegistryUri: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *string │ ├── RegionDetails: Object (3 properties)[] @@ -260,7 +262,9 @@ Workspace: Resource │ │ └── Status: *Enum (2 values) │ │ ├── "Active" │ │ └── "Inactive" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (7 properties) │ │ ├── AppInsightsInstrumentationKey: *genruntime.SecretDestination │ │ ├── ContainerRegistryPassword: *genruntime.SecretDestination @@ -489,7 +493,7 @@ Workspace: Resource └── WorkspaceId: *string WorkspacesCompute: Resource ├── Owner: Workspace -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Identity: *Object (2 properties) │ │ ├── Type: *Enum (4 values) @@ -500,6 +504,9 @@ WorkspacesCompute: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Properties: *Object (10 properties) │ │ ├── AKS: *Object (6 properties) @@ -1554,9 +1561,12 @@ WorkspacesCompute: Resource └── Type: *string WorkspacesConnection: Resource ├── Owner: Workspace -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z0-9][a-zA-Z0-9_-]{2,32}$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Properties: *Object (12 properties) │ ├── AAD: *Object (9 properties) diff --git a/v2/api/machinelearningservices/v1api20240401/workspace_types_gen.go b/v2/api/machinelearningservices/v1api20240401/workspace_types_gen.go index 39293ae473a..f0336aac560 100644 --- a/v2/api/machinelearningservices/v1api20240401/workspace_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/workspace_types_gen.go @@ -11,6 +11,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -93,6 +94,26 @@ func (workspace *Workspace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Workspace resource func (workspace *Workspace) defaultImpl() { workspace.defaultAzureName() } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Workspace{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +232,7 @@ func (workspace *Workspace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (workspace *Workspace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations, workspace.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations, workspace.validateConfigMapDestinations, workspace.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -232,12 +253,23 @@ func (workspace *Workspace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return workspace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return workspace.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (workspace *Workspace) validateConfigMapDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (workspace *Workspace) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&workspace.Spec) @@ -266,19 +298,19 @@ func (workspace *Workspace) validateSecretDestinations() (admission.Warnings, er if workspace.Spec.OperatorSpec == nil { return nil, nil } - if workspace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - workspace.Spec.OperatorSpec.Secrets.AppInsightsInstrumentationKey, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword2, - workspace.Spec.OperatorSpec.Secrets.ContainerRegistryUserName, - workspace.Spec.OperatorSpec.Secrets.PrimaryNotebookAccessKey, - workspace.Spec.OperatorSpec.Secrets.SecondaryNotebookAccessKey, - workspace.Spec.OperatorSpec.Secrets.UserStorageKey, + var toValidate []*genruntime.SecretDestination + if workspace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + workspace.Spec.OperatorSpec.Secrets.AppInsightsInstrumentationKey, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryPassword2, + workspace.Spec.OperatorSpec.Secrets.ContainerRegistryUserName, + workspace.Spec.OperatorSpec.Secrets.PrimaryNotebookAccessKey, + workspace.Spec.OperatorSpec.Secrets.SecondaryNotebookAccessKey, + workspace.Spec.OperatorSpec.Secrets.UserStorageKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(workspace, toValidate, workspace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -5058,6 +5090,12 @@ func (config *WorkspaceHubConfig_STATUS) AssignProperties_To_WorkspaceHubConfig_ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type WorkspaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *WorkspaceOperatorSecrets `json:"secrets,omitempty"` } @@ -5065,6 +5103,42 @@ type WorkspaceOperatorSpec struct { // AssignProperties_From_WorkspaceOperatorSpec populates our WorkspaceOperatorSpec from the provided source WorkspaceOperatorSpec func (operator *WorkspaceOperatorSpec) AssignProperties_From_WorkspaceOperatorSpec(source *storage.WorkspaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret WorkspaceOperatorSecrets @@ -5086,6 +5160,42 @@ func (operator *WorkspaceOperatorSpec) AssignProperties_To_WorkspaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.WorkspaceOperatorSecrets diff --git a/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen.go b/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen.go index 19d5c78fa19..ed3f30c5de3 100644 --- a/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -93,6 +95,26 @@ func (compute *WorkspacesCompute) defaultAzureName() { // defaultImpl applies the code generated defaults to the WorkspacesCompute resource func (compute *WorkspacesCompute) defaultImpl() { compute.defaultAzureName() } +var _ configmaps.Exporter = &WorkspacesCompute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (compute *WorkspacesCompute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesCompute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (compute *WorkspacesCompute) SecretDestinationExpressions() []*core.DestinationExpression { + if compute.Spec.OperatorSpec == nil { + return nil + } + return compute.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &WorkspacesCompute{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +233,7 @@ func (compute *WorkspacesCompute) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (compute *WorkspacesCompute) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){compute.validateResourceReferences, compute.validateOwnerReference, compute.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){compute.validateResourceReferences, compute.validateOwnerReference, compute.validateSecretDestinations, compute.validateConfigMapDestinations, compute.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -229,12 +251,26 @@ func (compute *WorkspacesCompute) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return compute.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return compute.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return compute.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return compute.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (compute *WorkspacesCompute) validateConfigMapDestinations() (admission.Warnings, error) { + if compute.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(compute, nil, compute.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (compute *WorkspacesCompute) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&compute.Spec) @@ -258,6 +294,14 @@ func (compute *WorkspacesCompute) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (compute *WorkspacesCompute) validateSecretDestinations() (admission.Warnings, error) { + if compute.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(compute, nil, compute.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (compute *WorkspacesCompute) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WorkspacesCompute) @@ -350,6 +394,10 @@ type WorkspacesCompute_Spec struct { // Location: Specifies the location of the resource. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspacesComputeOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -456,6 +504,8 @@ func (compute *WorkspacesCompute_Spec) PopulateFromARM(owner genruntime.Arbitrar compute.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": compute.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -567,6 +617,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_From_WorkspacesCompute_S // Location compute.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesComputeOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesComputeOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + compute.OperatorSpec = &operatorSpec + } else { + compute.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -629,6 +691,18 @@ func (compute *WorkspacesCompute_Spec) AssignProperties_To_WorkspacesCompute_Spe // Location destination.Location = genruntime.ClonePointerToString(compute.Location) + // OperatorSpec + if compute.OperatorSpec != nil { + var operatorSpec storage.WorkspacesComputeOperatorSpec + err := compute.OperatorSpec.AssignProperties_To_WorkspacesComputeOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesComputeOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = compute.OriginalVersion() @@ -2151,6 +2225,110 @@ func (compute *Compute_STATUS) AssignProperties_To_Compute_STATUS(destination *s return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesComputeOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesComputeOperatorSpec populates our WorkspacesComputeOperatorSpec from the provided source WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_From_WorkspacesComputeOperatorSpec(source *storage.WorkspacesComputeOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesComputeOperatorSpec populates the provided destination WorkspacesComputeOperatorSpec from our WorkspacesComputeOperatorSpec +func (operator *WorkspacesComputeOperatorSpec) AssignProperties_To_WorkspacesComputeOperatorSpec(destination *storage.WorkspacesComputeOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AKS struct { // ComputeLocation: Location for the underlying compute ComputeLocation *string `json:"computeLocation,omitempty"` diff --git a/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen_test.go b/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen_test.go index d2c95156b66..acdef6a458f 100644 --- a/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20240401/workspaces_compute_types_gen_test.go @@ -13688,6 +13688,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesCompute(gens map[string]gopter.Gen gens["Status"] = WorkspacesCompute_STATUSGenerator() } +func Test_WorkspacesComputeOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesComputeOperatorSpec to WorkspacesComputeOperatorSpec via AssignProperties_To_WorkspacesComputeOperatorSpec & AssignProperties_From_WorkspacesComputeOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec tests if a specific instance of WorkspacesComputeOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspacesComputeOperatorSpec + err := copied.AssignProperties_To_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesComputeOperatorSpec + err = actual.AssignProperties_From_WorkspacesComputeOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesComputeOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesComputeOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesComputeOperatorSpec, WorkspacesComputeOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesComputeOperatorSpec runs a test to see if a specific instance of WorkspacesComputeOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesComputeOperatorSpec(subject WorkspacesComputeOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesComputeOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesComputeOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesComputeOperatorSpecGenerator() +var workspacesComputeOperatorSpecGenerator gopter.Gen + +// WorkspacesComputeOperatorSpecGenerator returns a generator of WorkspacesComputeOperatorSpec instances for property testing. +func WorkspacesComputeOperatorSpecGenerator() gopter.Gen { + if workspacesComputeOperatorSpecGenerator != nil { + return workspacesComputeOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesComputeOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesComputeOperatorSpec{}), generators) + + return workspacesComputeOperatorSpecGenerator +} + func Test_WorkspacesCompute_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -13933,6 +14030,7 @@ func AddIndependentPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]g // AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesCompute_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesComputeOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(ComputeGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen.go b/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen.go index 638b5a2c9c1..83a26fcaf06 100644 --- a/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen.go +++ b/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (connection *WorkspacesConnection) defaultAzureName() { // defaultImpl applies the code generated defaults to the WorkspacesConnection resource func (connection *WorkspacesConnection) defaultImpl() { connection.defaultAzureName() } +var _ configmaps.Exporter = &WorkspacesConnection{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (connection *WorkspacesConnection) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesConnection{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (connection *WorkspacesConnection) SecretDestinationExpressions() []*core.DestinationExpression { + if connection.Spec.OperatorSpec == nil { + return nil + } + return connection.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &WorkspacesConnection{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (connection *WorkspacesConnection) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (connection *WorkspacesConnection) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){connection.validateResourceReferences, connection.validateOwnerReference, connection.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){connection.validateResourceReferences, connection.validateOwnerReference, connection.validateSecretDestinations, connection.validateConfigMapDestinations, connection.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (connection *WorkspacesConnection) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return connection.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return connection.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return connection.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return connection.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (connection *WorkspacesConnection) validateConfigMapDestinations() (admission.Warnings, error) { + if connection.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(connection, nil, connection.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (connection *WorkspacesConnection) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&connection.Spec) @@ -257,6 +293,14 @@ func (connection *WorkspacesConnection) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (connection *WorkspacesConnection) validateSecretDestinations() (admission.Warnings, error) { + if connection.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(connection, nil, connection.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (connection *WorkspacesConnection) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WorkspacesConnection) @@ -344,6 +388,10 @@ type WorkspacesConnection_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspacesConnectionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -393,6 +441,8 @@ func (connection *WorkspacesConnection_Spec) PopulateFromARM(owner genruntime.Ar // Set property "AzureName": connection.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": connection.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -470,6 +520,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_From_WorkspacesCon // AzureName connection.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesConnectionOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesConnectionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + connection.OperatorSpec = &operatorSpec + } else { + connection.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -502,6 +564,18 @@ func (connection *WorkspacesConnection_Spec) AssignProperties_To_WorkspacesConne // AzureName destination.AzureName = connection.AzureName + // OperatorSpec + if connection.OperatorSpec != nil { + var operatorSpec storage.WorkspacesConnectionOperatorSpec + err := connection.OperatorSpec.AssignProperties_To_WorkspacesConnectionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesConnectionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = connection.OriginalVersion() @@ -2067,6 +2141,110 @@ func (v2 *WorkspaceConnectionPropertiesV2_STATUS) AssignProperties_To_WorkspaceC return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesConnectionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesConnectionOperatorSpec populates our WorkspacesConnectionOperatorSpec from the provided source WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_From_WorkspacesConnectionOperatorSpec(source *storage.WorkspacesConnectionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesConnectionOperatorSpec populates the provided destination WorkspacesConnectionOperatorSpec from our WorkspacesConnectionOperatorSpec +func (operator *WorkspacesConnectionOperatorSpec) AssignProperties_To_WorkspacesConnectionOperatorSpec(destination *storage.WorkspacesConnectionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AADAuthTypeWorkspaceConnectionProperties struct { // +kubebuilder:validation:Required // AuthType: Authentication type of the connection target diff --git a/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen_test.go b/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen_test.go index 0f42e88c826..2f0c4a43418 100644 --- a/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen_test.go +++ b/v2/api/machinelearningservices/v1api20240401/workspaces_connection_types_gen_test.go @@ -8016,6 +8016,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesConnection(gens map[string]gopter. gens["Status"] = WorkspacesConnection_STATUSGenerator() } +func Test_WorkspacesConnectionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesConnectionOperatorSpec to WorkspacesConnectionOperatorSpec via AssignProperties_To_WorkspacesConnectionOperatorSpec & AssignProperties_From_WorkspacesConnectionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec tests if a specific instance of WorkspacesConnectionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspacesConnectionOperatorSpec + err := copied.AssignProperties_To_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesConnectionOperatorSpec + err = actual.AssignProperties_From_WorkspacesConnectionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesConnectionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesConnectionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesConnectionOperatorSpec, WorkspacesConnectionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesConnectionOperatorSpec runs a test to see if a specific instance of WorkspacesConnectionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesConnectionOperatorSpec(subject WorkspacesConnectionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesConnectionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesConnectionOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesConnectionOperatorSpecGenerator() +var workspacesConnectionOperatorSpecGenerator gopter.Gen + +// WorkspacesConnectionOperatorSpecGenerator returns a generator of WorkspacesConnectionOperatorSpec instances for property testing. +func WorkspacesConnectionOperatorSpecGenerator() gopter.Gen { + if workspacesConnectionOperatorSpecGenerator != nil { + return workspacesConnectionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesConnectionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesConnectionOperatorSpec{}), generators) + + return workspacesConnectionOperatorSpecGenerator +} + func Test_WorkspacesConnection_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -8250,5 +8347,6 @@ func AddIndependentPropertyGeneratorsForWorkspacesConnection_Spec(gens map[strin // AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspacesConnection_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(WorkspacesConnectionOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(WorkspaceConnectionPropertiesV2Generator()) } diff --git a/v2/api/machinelearningservices/v1api20240401/zz_generated.deepcopy.go b/v2/api/machinelearningservices/v1api20240401/zz_generated.deepcopy.go index 9b11e62fcd2..d81f26b4414 100644 --- a/v2/api/machinelearningservices/v1api20240401/zz_generated.deepcopy.go +++ b/v2/api/machinelearningservices/v1api20240401/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20240401 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -5883,11 +5884,33 @@ func (in *RegistryOperatorConfigMaps) DeepCopy() *RegistryOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RegistryOperatorSpec) DeepCopyInto(out *RegistryOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(RegistryOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RegistryOperatorSpec. @@ -9476,6 +9499,28 @@ func (in *WorkspaceOperatorSecrets) DeepCopy() *WorkspaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(WorkspaceOperatorSecrets) @@ -9954,6 +9999,43 @@ func (in *WorkspacesComputeList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesComputeOperatorSpec) DeepCopyInto(out *WorkspacesComputeOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesComputeOperatorSpec. +func (in *WorkspacesComputeOperatorSpec) DeepCopy() *WorkspacesComputeOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesComputeOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesCompute_STATUS) DeepCopyInto(out *WorkspacesCompute_STATUS) { *out = *in @@ -10036,6 +10118,11 @@ func (in *WorkspacesCompute_Spec) DeepCopyInto(out *WorkspacesCompute_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesComputeOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -10129,6 +10216,43 @@ func (in *WorkspacesConnectionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesConnectionOperatorSpec) DeepCopyInto(out *WorkspacesConnectionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesConnectionOperatorSpec. +func (in *WorkspacesConnectionOperatorSpec) DeepCopy() *WorkspacesConnectionOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesConnectionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_STATUS) DeepCopyInto(out *WorkspacesConnection_STATUS) { *out = *in @@ -10179,6 +10303,11 @@ func (in *WorkspacesConnection_STATUS) DeepCopy() *WorkspacesConnection_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesConnection_Spec) DeepCopyInto(out *WorkspacesConnection_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesConnectionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/managedidentity/v1api20181130/storage/structure.txt b/v2/api/managedidentity/v1api20181130/storage/structure.txt index f7d7bdb9d31..9be0d50792c 100644 --- a/v2/api/managedidentity/v1api20181130/storage/structure.txt +++ b/v2/api/managedidentity/v1api20181130/storage/structure.txt @@ -8,13 +8,15 @@ UserAssignedIdentity: Resource ├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (4 properties) │ │ │ ├── ClientId: *genruntime.ConfigMapDestination │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── TenantId: *genruntime.ConfigMapDestination -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/managedidentity/v1api20181130/storage/user_assigned_identity_types_gen.go b/v2/api/managedidentity/v1api20181130/storage/user_assigned_identity_types_gen.go index 1c193abc8e3..c8a5af28484 100644 --- a/v2/api/managedidentity/v1api20181130/storage/user_assigned_identity_types_gen.go +++ b/v2/api/managedidentity/v1api20181130/storage/user_assigned_identity_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -70,6 +72,26 @@ func (identity *UserAssignedIdentity) ConvertTo(hub conversion.Hub) error { return identity.AssignProperties_To_UserAssignedIdentity(destination) } +var _ configmaps.Exporter = &UserAssignedIdentity{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (identity *UserAssignedIdentity) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &UserAssignedIdentity{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (identity *UserAssignedIdentity) SecretDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &UserAssignedIdentity{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -652,8 +674,10 @@ type augmentConversionForUserAssignedIdentity_STATUS interface { // Storage version of v1api20181130.UserAssignedIdentityOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type UserAssignedIdentityOperatorSpec struct { - ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_UserAssignedIdentityOperatorSpec populates our UserAssignedIdentityOperatorSpec from the provided source UserAssignedIdentityOperatorSpec @@ -661,6 +685,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssi // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap UserAssignedIdentityOperatorConfigMaps @@ -673,6 +715,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssi operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { propertyBag.Add("Secrets", *source.Secrets) @@ -705,6 +765,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.UserAssignedIdentityOperatorConfigMaps @@ -717,6 +795,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if propertyBag.Contains("Secrets") { var secret storage.UserAssignedIdentityOperatorSecrets diff --git a/v2/api/managedidentity/v1api20181130/storage/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20181130/storage/zz_generated.deepcopy.go index dbf4e402c0c..7f339944b38 100644 --- a/v2/api/managedidentity/v1api20181130/storage/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20181130/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -114,6 +115,17 @@ func (in *UserAssignedIdentityOperatorConfigMaps) DeepCopy() *UserAssignedIdenti // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdentityOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(UserAssignedIdentityOperatorConfigMaps) @@ -126,6 +138,17 @@ func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdenti (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserAssignedIdentityOperatorSpec. diff --git a/v2/api/managedidentity/v1api20181130/structure.txt b/v2/api/managedidentity/v1api20181130/structure.txt index 4e8c27c3d0b..0f9ced1e37e 100644 --- a/v2/api/managedidentity/v1api20181130/structure.txt +++ b/v2/api/managedidentity/v1api20181130/structure.txt @@ -8,11 +8,13 @@ UserAssignedIdentity: Resource ├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (3 properties) -│ │ ├── ClientId: *genruntime.ConfigMapDestination -│ │ ├── PrincipalId: *genruntime.ConfigMapDestination -│ │ └── TenantId: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (3 properties) +│ │ │ ├── ClientId: *genruntime.ConfigMapDestination +│ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination +│ │ │ └── TenantId: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (9 properties) diff --git a/v2/api/managedidentity/v1api20181130/user_assigned_identity_types_gen.go b/v2/api/managedidentity/v1api20181130/user_assigned_identity_types_gen.go index b4353071df2..38d4bbf8efb 100644 --- a/v2/api/managedidentity/v1api20181130/user_assigned_identity_types_gen.go +++ b/v2/api/managedidentity/v1api20181130/user_assigned_identity_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -110,6 +112,26 @@ func (identity *UserAssignedIdentity) defaultAzureName() { // defaultImpl applies the code generated defaults to the UserAssignedIdentity resource func (identity *UserAssignedIdentity) defaultImpl() { identity.defaultAzureName() } +var _ configmaps.Exporter = &UserAssignedIdentity{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (identity *UserAssignedIdentity) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &UserAssignedIdentity{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (identity *UserAssignedIdentity) SecretDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &UserAssignedIdentity{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -244,7 +266,7 @@ func (identity *UserAssignedIdentity) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (identity *UserAssignedIdentity) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){identity.validateResourceReferences, identity.validateOwnerReference, identity.validateConfigMapDestinations} + return []func() (admission.Warnings, error){identity.validateResourceReferences, identity.validateOwnerReference, identity.validateSecretDestinations, identity.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -262,6 +284,9 @@ func (identity *UserAssignedIdentity) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return identity.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return identity.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return identity.validateConfigMapDestinations() }, @@ -273,15 +298,15 @@ func (identity *UserAssignedIdentity) validateConfigMapDestinations() (admission if identity.Spec.OperatorSpec == nil { return nil, nil } - if identity.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - identity.Spec.OperatorSpec.ConfigMaps.ClientId, - identity.Spec.OperatorSpec.ConfigMaps.PrincipalId, - identity.Spec.OperatorSpec.ConfigMaps.TenantId, + var toValidate []*genruntime.ConfigMapDestination + if identity.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + identity.Spec.OperatorSpec.ConfigMaps.ClientId, + identity.Spec.OperatorSpec.ConfigMaps.PrincipalId, + identity.Spec.OperatorSpec.ConfigMaps.TenantId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(identity, toValidate, identity.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -298,6 +323,14 @@ func (identity *UserAssignedIdentity) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (identity *UserAssignedIdentity) validateSecretDestinations() (admission.Warnings, error) { + if identity.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(identity, nil, identity.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (identity *UserAssignedIdentity) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*UserAssignedIdentity) @@ -858,13 +891,37 @@ func (identity *UserAssignedIdentity_STATUS) AssignProperties_To_UserAssignedIde // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type UserAssignedIdentityOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_UserAssignedIdentityOperatorSpec populates our UserAssignedIdentityOperatorSpec from the provided source UserAssignedIdentityOperatorSpec func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssignedIdentityOperatorSpec(source *storage.UserAssignedIdentityOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap UserAssignedIdentityOperatorConfigMaps @@ -877,6 +934,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssi operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -886,6 +961,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.UserAssignedIdentityOperatorConfigMaps @@ -898,6 +991,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/managedidentity/v1api20181130/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20181130/zz_generated.deepcopy.go index c18725d7ff7..5458b7bd54b 100644 --- a/v2/api/managedidentity/v1api20181130/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20181130/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20181130 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -107,11 +108,33 @@ func (in *UserAssignedIdentityOperatorConfigMaps) DeepCopy() *UserAssignedIdenti // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdentityOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(UserAssignedIdentityOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserAssignedIdentityOperatorSpec. diff --git a/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen.go b/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen.go index 2e6cedcf563..902287ec1e9 100644 --- a/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen.go +++ b/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -106,6 +108,26 @@ func (credential *FederatedIdentityCredential) defaultAzureName() { // defaultImpl applies the code generated defaults to the FederatedIdentityCredential resource func (credential *FederatedIdentityCredential) defaultImpl() { credential.defaultAzureName() } +var _ configmaps.Exporter = &FederatedIdentityCredential{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (credential *FederatedIdentityCredential) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FederatedIdentityCredential{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (credential *FederatedIdentityCredential) SecretDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FederatedIdentityCredential{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (credential *FederatedIdentityCredential) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (credential *FederatedIdentityCredential) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){credential.validateResourceReferences, credential.validateOwnerReference, credential.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){credential.validateResourceReferences, credential.validateOwnerReference, credential.validateSecretDestinations, credential.validateConfigMapDestinations, credential.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -231,12 +253,26 @@ func (credential *FederatedIdentityCredential) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return credential.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return credential.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return credential.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return credential.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (credential *FederatedIdentityCredential) validateConfigMapDestinations() (admission.Warnings, error) { + if credential.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(credential, nil, credential.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (credential *FederatedIdentityCredential) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&credential.Spec) @@ -260,6 +296,14 @@ func (credential *FederatedIdentityCredential) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (credential *FederatedIdentityCredential) validateSecretDestinations() (admission.Warnings, error) { + if credential.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(credential, nil, credential.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (credential *FederatedIdentityCredential) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FederatedIdentityCredential) @@ -361,6 +405,10 @@ type FederatedIdentityCredential_Spec struct { // IssuerFromConfig: The URL of the issuer to be trusted. IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FederatedIdentityCredentialOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -458,6 +506,8 @@ func (credential *FederatedIdentityCredential_Spec) PopulateFromARM(owner genrun // no assignment for property "IssuerFromConfig" + // no assignment for property "OperatorSpec" + // Set property "Owner": credential.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -549,6 +599,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_From_Federa credential.IssuerFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FederatedIdentityCredentialOperatorSpec + err := operatorSpec.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + credential.OperatorSpec = &operatorSpec + } else { + credential.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -594,6 +656,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_To_Federate destination.IssuerFromConfig = nil } + // OperatorSpec + if credential.OperatorSpec != nil { + var operatorSpec storage.FederatedIdentityCredentialOperatorSpec + err := credential.OperatorSpec.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = credential.OriginalVersion() @@ -840,6 +914,110 @@ func (credential *FederatedIdentityCredential_STATUS) AssignProperties_To_Federa return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FederatedIdentityCredentialOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FederatedIdentityCredentialOperatorSpec populates our FederatedIdentityCredentialOperatorSpec from the provided source FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source *storage.FederatedIdentityCredentialOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FederatedIdentityCredentialOperatorSpec populates the provided destination FederatedIdentityCredentialOperatorSpec from our FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_To_FederatedIdentityCredentialOperatorSpec(destination *storage.FederatedIdentityCredentialOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FederatedIdentityCredential{}, &FederatedIdentityCredentialList{}) } diff --git a/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen_test.go b/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen_test.go index fd915f759ae..48cdcc2a3bf 100644 --- a/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen_test.go +++ b/v2/api/managedidentity/v1api20220131preview/federated_identity_credential_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForFederatedIdentityCredential(gens map[string] gens["Status"] = FederatedIdentityCredential_STATUSGenerator() } +func Test_FederatedIdentityCredentialOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FederatedIdentityCredentialOperatorSpec to FederatedIdentityCredentialOperatorSpec via AssignProperties_To_FederatedIdentityCredentialOperatorSpec & AssignProperties_From_FederatedIdentityCredentialOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec tests if a specific instance of FederatedIdentityCredentialOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220131ps.FederatedIdentityCredentialOperatorSpec + err := copied.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FederatedIdentityCredentialOperatorSpec + err = actual.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FederatedIdentityCredentialOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FederatedIdentityCredentialOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec runs a test to see if a specific instance of FederatedIdentityCredentialOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FederatedIdentityCredentialOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FederatedIdentityCredentialOperatorSpec instances for property testing - lazily instantiated by +// FederatedIdentityCredentialOperatorSpecGenerator() +var federatedIdentityCredentialOperatorSpecGenerator gopter.Gen + +// FederatedIdentityCredentialOperatorSpecGenerator returns a generator of FederatedIdentityCredentialOperatorSpec instances for property testing. +func FederatedIdentityCredentialOperatorSpecGenerator() gopter.Gen { + if federatedIdentityCredentialOperatorSpecGenerator != nil { + return federatedIdentityCredentialOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + federatedIdentityCredentialOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredentialOperatorSpec{}), generators) + + return federatedIdentityCredentialOperatorSpecGenerator +} + func Test_FederatedIdentityCredential_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForFederatedIdentityCredential_Spec(subject Federat var federatedIdentityCredential_SpecGenerator gopter.Gen // FederatedIdentityCredential_SpecGenerator returns a generator of FederatedIdentityCredential_Spec instances for property testing. +// We first initialize federatedIdentityCredential_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FederatedIdentityCredential_SpecGenerator() gopter.Gen { if federatedIdentityCredential_SpecGenerator != nil { return federatedIdentityCredential_SpecGenerator @@ -369,6 +469,12 @@ func FederatedIdentityCredential_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + return federatedIdentityCredential_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(gens ma gens["Issuer"] = gen.PtrOf(gen.AlphaString()) gens["Subject"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FederatedIdentityCredentialOperatorSpecGenerator()) +} diff --git a/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen.go b/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen.go index b57ffc2a2a9..d3f4559c86f 100644 --- a/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen.go +++ b/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/managedidentity/v1api20230131/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (credential *FederatedIdentityCredential) ConvertTo(hub conversion.Hub) err return credential.AssignProperties_To_FederatedIdentityCredential(destination) } +var _ configmaps.Exporter = &FederatedIdentityCredential{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (credential *FederatedIdentityCredential) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FederatedIdentityCredential{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (credential *FederatedIdentityCredential) SecretDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FederatedIdentityCredential{} // AzureName returns the Azure name of the resource @@ -243,10 +266,11 @@ type FederatedIdentityCredential_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Issuer *string `json:"issuer,omitempty" optionalConfigMapPair:"Issuer"` - IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Issuer *string `json:"issuer,omitempty" optionalConfigMapPair:"Issuer"` + IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` + OperatorSpec *FederatedIdentityCredentialOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -330,6 +354,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_From_Federa credential.IssuerFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FederatedIdentityCredentialOperatorSpec + err := operatorSpec.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + credential.OperatorSpec = &operatorSpec + } else { + credential.OperatorSpec = nil + } + // OriginalVersion credential.OriginalVersion = source.OriginalVersion @@ -394,6 +430,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_To_Federate destination.IssuerFromConfig = nil } + // OperatorSpec + if credential.OperatorSpec != nil { + var operatorSpec storage.FederatedIdentityCredentialOperatorSpec + err := credential.OperatorSpec.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = credential.OriginalVersion @@ -620,6 +668,141 @@ type augmentConversionForFederatedIdentityCredential_STATUS interface { AssignPropertiesTo(dst *storage.FederatedIdentityCredential_STATUS) error } +// Storage version of v1api20220131preview.FederatedIdentityCredentialOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FederatedIdentityCredentialOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FederatedIdentityCredentialOperatorSpec populates our FederatedIdentityCredentialOperatorSpec from the provided source FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source *storage.FederatedIdentityCredentialOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForFederatedIdentityCredentialOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFederatedIdentityCredentialOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_FederatedIdentityCredentialOperatorSpec populates the provided destination FederatedIdentityCredentialOperatorSpec from our FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_To_FederatedIdentityCredentialOperatorSpec(destination *storage.FederatedIdentityCredentialOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForFederatedIdentityCredentialOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForFederatedIdentityCredentialOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForFederatedIdentityCredentialOperatorSpec interface { + AssignPropertiesFrom(src *storage.FederatedIdentityCredentialOperatorSpec) error + AssignPropertiesTo(dst *storage.FederatedIdentityCredentialOperatorSpec) error +} + func init() { SchemeBuilder.Register(&FederatedIdentityCredential{}, &FederatedIdentityCredentialList{}) } diff --git a/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen_test.go b/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen_test.go index 2d11d3500cb..586b88775f1 100644 --- a/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen_test.go +++ b/v2/api/managedidentity/v1api20220131preview/storage/federated_identity_credential_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFederatedIdentityCredential(gens map[string] gens["Status"] = FederatedIdentityCredential_STATUSGenerator() } +func Test_FederatedIdentityCredentialOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FederatedIdentityCredentialOperatorSpec to FederatedIdentityCredentialOperatorSpec via AssignProperties_To_FederatedIdentityCredentialOperatorSpec & AssignProperties_From_FederatedIdentityCredentialOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec tests if a specific instance of FederatedIdentityCredentialOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FederatedIdentityCredentialOperatorSpec + err := copied.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FederatedIdentityCredentialOperatorSpec + err = actual.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FederatedIdentityCredentialOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FederatedIdentityCredentialOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec runs a test to see if a specific instance of FederatedIdentityCredentialOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FederatedIdentityCredentialOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FederatedIdentityCredentialOperatorSpec instances for property testing - lazily instantiated by +// FederatedIdentityCredentialOperatorSpecGenerator() +var federatedIdentityCredentialOperatorSpecGenerator gopter.Gen + +// FederatedIdentityCredentialOperatorSpecGenerator returns a generator of FederatedIdentityCredentialOperatorSpec instances for property testing. +func FederatedIdentityCredentialOperatorSpecGenerator() gopter.Gen { + if federatedIdentityCredentialOperatorSpecGenerator != nil { + return federatedIdentityCredentialOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + federatedIdentityCredentialOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredentialOperatorSpec{}), generators) + + return federatedIdentityCredentialOperatorSpecGenerator +} + func Test_FederatedIdentityCredential_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForFederatedIdentityCredential_Spec(subject Federat var federatedIdentityCredential_SpecGenerator gopter.Gen // FederatedIdentityCredential_SpecGenerator returns a generator of FederatedIdentityCredential_Spec instances for property testing. +// We first initialize federatedIdentityCredential_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FederatedIdentityCredential_SpecGenerator() gopter.Gen { if federatedIdentityCredential_SpecGenerator != nil { return federatedIdentityCredential_SpecGenerator @@ -368,6 +468,12 @@ func FederatedIdentityCredential_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + return federatedIdentityCredential_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(gens ma gens["OriginalVersion"] = gen.AlphaString() gens["Subject"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FederatedIdentityCredentialOperatorSpecGenerator()) +} diff --git a/v2/api/managedidentity/v1api20220131preview/storage/structure.txt b/v2/api/managedidentity/v1api20220131preview/storage/structure.txt index 83a47d2c933..1e0328a5e89 100644 --- a/v2/api/managedidentity/v1api20220131preview/storage/structure.txt +++ b/v2/api/managedidentity/v1api20220131preview/storage/structure.txt @@ -5,11 +5,15 @@ APIVersion: Enum (1 value) └── "2022-01-31-preview" FederatedIdentityCredential: Resource ├── Owner: managedidentity/v1api20220131preview.UserAssignedIdentity -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── Audiences: string[] │ ├── AzureName: string │ ├── Issuer: *string │ ├── IssuerFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -25,5 +29,6 @@ FederatedIdentityCredential: Resource ├── Subject: *string └── Type: *string augmentConversionForFederatedIdentityCredential: Interface +augmentConversionForFederatedIdentityCredentialOperatorSpec: Interface augmentConversionForFederatedIdentityCredential_STATUS: Interface augmentConversionForFederatedIdentityCredential_Spec: Interface diff --git a/v2/api/managedidentity/v1api20220131preview/storage/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20220131preview/storage/zz_generated.deepcopy.go index 4bfe897778f..bc0da9567b8 100644 --- a/v2/api/managedidentity/v1api20220131preview/storage/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20220131preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *FederatedIdentityCredentialList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopyInto(out *FederatedIdentityCredentialOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedIdentityCredentialOperatorSpec. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopy() *FederatedIdentityCredentialOperatorSpec { + if in == nil { + return nil + } + out := new(FederatedIdentityCredentialOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FederatedIdentityCredential_STATUS) DeepCopyInto(out *FederatedIdentityCredential_STATUS) { *out = *in @@ -151,6 +196,11 @@ func (in *FederatedIdentityCredential_Spec) DeepCopyInto(out *FederatedIdentityC *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FederatedIdentityCredentialOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/managedidentity/v1api20220131preview/structure.txt b/v2/api/managedidentity/v1api20220131preview/structure.txt index 7dd7405f7bd..d5b1871750b 100644 --- a/v2/api/managedidentity/v1api20220131preview/structure.txt +++ b/v2/api/managedidentity/v1api20220131preview/structure.txt @@ -5,11 +5,14 @@ APIVersion: Enum (1 value) └── "2022-01-31-preview" FederatedIdentityCredential: Resource ├── Owner: UserAssignedIdentity -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── Audiences: string[] │ ├── AzureName: string │ ├── Issuer: *string │ ├── IssuerFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Subject: *string │ └── SubjectFromConfig: *genruntime.ConfigMapReference diff --git a/v2/api/managedidentity/v1api20220131preview/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20220131preview/zz_generated.deepcopy.go index 1da5b9a26f4..402ea92a9dc 100644 --- a/v2/api/managedidentity/v1api20220131preview/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20220131preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220131preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *FederatedIdentityCredentialList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopyInto(out *FederatedIdentityCredentialOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedIdentityCredentialOperatorSpec. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopy() *FederatedIdentityCredentialOperatorSpec { + if in == nil { + return nil + } + out := new(FederatedIdentityCredentialOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FederatedIdentityCredential_STATUS) DeepCopyInto(out *FederatedIdentityCredential_STATUS) { *out = *in @@ -144,6 +182,11 @@ func (in *FederatedIdentityCredential_Spec) DeepCopyInto(out *FederatedIdentityC *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FederatedIdentityCredentialOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen.go b/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen.go index 16789589c20..1da939e52f0 100644 --- a/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen.go +++ b/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (credential *FederatedIdentityCredential) defaultAzureName() { // defaultImpl applies the code generated defaults to the FederatedIdentityCredential resource func (credential *FederatedIdentityCredential) defaultImpl() { credential.defaultAzureName() } +var _ configmaps.Exporter = &FederatedIdentityCredential{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (credential *FederatedIdentityCredential) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FederatedIdentityCredential{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (credential *FederatedIdentityCredential) SecretDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &FederatedIdentityCredential{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (credential *FederatedIdentityCredential) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (credential *FederatedIdentityCredential) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){credential.validateResourceReferences, credential.validateOwnerReference, credential.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){credential.validateResourceReferences, credential.validateOwnerReference, credential.validateSecretDestinations, credential.validateConfigMapDestinations, credential.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (credential *FederatedIdentityCredential) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return credential.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return credential.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return credential.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return credential.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (credential *FederatedIdentityCredential) validateConfigMapDestinations() (admission.Warnings, error) { + if credential.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(credential, nil, credential.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (credential *FederatedIdentityCredential) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&credential.Spec) @@ -257,6 +293,14 @@ func (credential *FederatedIdentityCredential) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (credential *FederatedIdentityCredential) validateSecretDestinations() (admission.Warnings, error) { + if credential.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(credential, nil, credential.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (credential *FederatedIdentityCredential) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FederatedIdentityCredential) @@ -359,6 +403,10 @@ type FederatedIdentityCredential_Spec struct { // IssuerFromConfig: The URL of the issuer to be trusted. IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FederatedIdentityCredentialOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -456,6 +504,8 @@ func (credential *FederatedIdentityCredential_Spec) PopulateFromARM(owner genrun // no assignment for property "IssuerFromConfig" + // no assignment for property "OperatorSpec" + // Set property "Owner": credential.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -547,6 +597,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_From_Federa credential.IssuerFromConfig = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FederatedIdentityCredentialOperatorSpec + err := operatorSpec.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + credential.OperatorSpec = &operatorSpec + } else { + credential.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -592,6 +654,18 @@ func (credential *FederatedIdentityCredential_Spec) AssignProperties_To_Federate destination.IssuerFromConfig = nil } + // OperatorSpec + if credential.OperatorSpec != nil { + var operatorSpec storage.FederatedIdentityCredentialOperatorSpec + err := credential.OperatorSpec.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FederatedIdentityCredentialOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = credential.OriginalVersion() @@ -892,6 +966,110 @@ func (credential *FederatedIdentityCredential_STATUS) AssignProperties_To_Federa return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FederatedIdentityCredentialOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FederatedIdentityCredentialOperatorSpec populates our FederatedIdentityCredentialOperatorSpec from the provided source FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_From_FederatedIdentityCredentialOperatorSpec(source *storage.FederatedIdentityCredentialOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FederatedIdentityCredentialOperatorSpec populates the provided destination FederatedIdentityCredentialOperatorSpec from our FederatedIdentityCredentialOperatorSpec +func (operator *FederatedIdentityCredentialOperatorSpec) AssignProperties_To_FederatedIdentityCredentialOperatorSpec(destination *storage.FederatedIdentityCredentialOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen_test.go b/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen_test.go index 6987aad47f1..a690ec45496 100644 --- a/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen_test.go +++ b/v2/api/managedidentity/v1api20230131/federated_identity_credential_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForFederatedIdentityCredential(gens map[string] gens["Status"] = FederatedIdentityCredential_STATUSGenerator() } +func Test_FederatedIdentityCredentialOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from FederatedIdentityCredentialOperatorSpec to FederatedIdentityCredentialOperatorSpec via AssignProperties_To_FederatedIdentityCredentialOperatorSpec & AssignProperties_From_FederatedIdentityCredentialOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec tests if a specific instance of FederatedIdentityCredentialOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.FederatedIdentityCredentialOperatorSpec + err := copied.AssignProperties_To_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual FederatedIdentityCredentialOperatorSpec + err = actual.AssignProperties_From_FederatedIdentityCredentialOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_FederatedIdentityCredentialOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FederatedIdentityCredentialOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec runs a test to see if a specific instance of FederatedIdentityCredentialOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FederatedIdentityCredentialOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FederatedIdentityCredentialOperatorSpec instances for property testing - lazily instantiated by +// FederatedIdentityCredentialOperatorSpecGenerator() +var federatedIdentityCredentialOperatorSpecGenerator gopter.Gen + +// FederatedIdentityCredentialOperatorSpecGenerator returns a generator of FederatedIdentityCredentialOperatorSpec instances for property testing. +func FederatedIdentityCredentialOperatorSpecGenerator() gopter.Gen { + if federatedIdentityCredentialOperatorSpecGenerator != nil { + return federatedIdentityCredentialOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + federatedIdentityCredentialOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredentialOperatorSpec{}), generators) + + return federatedIdentityCredentialOperatorSpecGenerator +} + func Test_FederatedIdentityCredential_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForFederatedIdentityCredential_Spec(subject Federat var federatedIdentityCredential_SpecGenerator gopter.Gen // FederatedIdentityCredential_SpecGenerator returns a generator of FederatedIdentityCredential_Spec instances for property testing. +// We first initialize federatedIdentityCredential_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FederatedIdentityCredential_SpecGenerator() gopter.Gen { if federatedIdentityCredential_SpecGenerator != nil { return federatedIdentityCredential_SpecGenerator @@ -382,6 +482,12 @@ func FederatedIdentityCredential_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + return federatedIdentityCredential_SpecGenerator } @@ -393,6 +499,11 @@ func AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(gens ma gens["Subject"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FederatedIdentityCredentialOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen.go b/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen.go index 1eb85ba700d..f8ef1e2102f 100644 --- a/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen.go +++ b/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (credential *FederatedIdentityCredential) SetConditions(conditions conditio credential.Status.Conditions = conditions } +var _ configmaps.Exporter = &FederatedIdentityCredential{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (credential *FederatedIdentityCredential) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FederatedIdentityCredential{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (credential *FederatedIdentityCredential) SecretDestinationExpressions() []*core.DestinationExpression { + if credential.Spec.OperatorSpec == nil { + return nil + } + return credential.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FederatedIdentityCredential{} // AzureName returns the Azure name of the resource @@ -150,10 +173,11 @@ type FederatedIdentityCredential_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Issuer *string `json:"issuer,omitempty" optionalConfigMapPair:"Issuer"` - IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Issuer *string `json:"issuer,omitempty" optionalConfigMapPair:"Issuer"` + IssuerFromConfig *genruntime.ConfigMapReference `json:"issuerFromConfig,omitempty" optionalConfigMapPair:"Issuer"` + OperatorSpec *FederatedIdentityCredentialOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -218,6 +242,14 @@ func (credential *FederatedIdentityCredential_STATUS) ConvertStatusTo(destinatio return destination.ConvertStatusFrom(credential) } +// Storage version of v1api20230131.FederatedIdentityCredentialOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FederatedIdentityCredentialOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230131.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen_test.go b/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen_test.go index 1a77812e4bf..2589ac13146 100644 --- a/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen_test.go +++ b/v2/api/managedidentity/v1api20230131/storage/federated_identity_credential_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForFederatedIdentityCredential(gens map[string] gens["Status"] = FederatedIdentityCredential_STATUSGenerator() } +func Test_FederatedIdentityCredentialOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of FederatedIdentityCredentialOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec, FederatedIdentityCredentialOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec runs a test to see if a specific instance of FederatedIdentityCredentialOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForFederatedIdentityCredentialOperatorSpec(subject FederatedIdentityCredentialOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual FederatedIdentityCredentialOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of FederatedIdentityCredentialOperatorSpec instances for property testing - lazily instantiated by +// FederatedIdentityCredentialOperatorSpecGenerator() +var federatedIdentityCredentialOperatorSpecGenerator gopter.Gen + +// FederatedIdentityCredentialOperatorSpecGenerator returns a generator of FederatedIdentityCredentialOperatorSpec instances for property testing. +func FederatedIdentityCredentialOperatorSpecGenerator() gopter.Gen { + if federatedIdentityCredentialOperatorSpecGenerator != nil { + return federatedIdentityCredentialOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + federatedIdentityCredentialOperatorSpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredentialOperatorSpec{}), generators) + + return federatedIdentityCredentialOperatorSpecGenerator +} + func Test_FederatedIdentityCredential_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -203,6 +258,9 @@ func RunJSONSerializationTestForFederatedIdentityCredential_Spec(subject Federat var federatedIdentityCredential_SpecGenerator gopter.Gen // FederatedIdentityCredential_SpecGenerator returns a generator of FederatedIdentityCredential_Spec instances for property testing. +// We first initialize federatedIdentityCredential_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func FederatedIdentityCredential_SpecGenerator() gopter.Gen { if federatedIdentityCredential_SpecGenerator != nil { return federatedIdentityCredential_SpecGenerator @@ -212,6 +270,12 @@ func FederatedIdentityCredential_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(generators) + federatedIdentityCredential_SpecGenerator = gen.Struct(reflect.TypeOf(FederatedIdentityCredential_Spec{}), generators) + return federatedIdentityCredential_SpecGenerator } @@ -224,6 +288,11 @@ func AddIndependentPropertyGeneratorsForFederatedIdentityCredential_Spec(gens ma gens["Subject"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForFederatedIdentityCredential_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(FederatedIdentityCredentialOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/managedidentity/v1api20230131/storage/structure.txt b/v2/api/managedidentity/v1api20230131/storage/structure.txt index e1c0bd528e2..4f4f8da4ad3 100644 --- a/v2/api/managedidentity/v1api20230131/storage/structure.txt +++ b/v2/api/managedidentity/v1api20230131/storage/structure.txt @@ -5,11 +5,15 @@ APIVersion: Enum (1 value) └── "2023-01-31" FederatedIdentityCredential: Resource ├── Owner: managedidentity/v1api20230131.UserAssignedIdentity -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── Audiences: string[] │ ├── AzureName: string │ ├── Issuer: *string │ ├── IssuerFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -37,13 +41,15 @@ UserAssignedIdentity: Resource ├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (4 properties) │ │ │ ├── ClientId: *genruntime.ConfigMapDestination │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── TenantId: *genruntime.ConfigMapDestination │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── ClientId: *genruntime.SecretDestination │ │ ├── PrincipalId: *genruntime.SecretDestination diff --git a/v2/api/managedidentity/v1api20230131/storage/user_assigned_identity_types_gen.go b/v2/api/managedidentity/v1api20230131/storage/user_assigned_identity_types_gen.go index 3a87b72e75e..cb7ff67d034 100644 --- a/v2/api/managedidentity/v1api20230131/storage/user_assigned_identity_types_gen.go +++ b/v2/api/managedidentity/v1api20230131/storage/user_assigned_identity_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (identity *UserAssignedIdentity) SetConditions(conditions conditions.Condit identity.Status.Conditions = conditions } +var _ configmaps.Exporter = &UserAssignedIdentity{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (identity *UserAssignedIdentity) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &UserAssignedIdentity{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (identity *UserAssignedIdentity) SecretDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &UserAssignedIdentity{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -246,9 +268,11 @@ func (identity *UserAssignedIdentity_STATUS) ConvertStatusTo(destination genrunt // Storage version of v1api20230131.UserAssignedIdentityOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type UserAssignedIdentityOperatorSpec struct { - ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *UserAssignedIdentityOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *UserAssignedIdentityOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20230131.UserAssignedIdentityOperatorConfigMaps diff --git a/v2/api/managedidentity/v1api20230131/storage/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20230131/storage/zz_generated.deepcopy.go index dcc8a997ed4..ad81577972f 100644 --- a/v2/api/managedidentity/v1api20230131/storage/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20230131/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *FederatedIdentityCredentialList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopyInto(out *FederatedIdentityCredentialOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedIdentityCredentialOperatorSpec. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopy() *FederatedIdentityCredentialOperatorSpec { + if in == nil { + return nil + } + out := new(FederatedIdentityCredentialOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FederatedIdentityCredential_STATUS) DeepCopyInto(out *FederatedIdentityCredential_STATUS) { *out = *in @@ -156,6 +201,11 @@ func (in *FederatedIdentityCredential_Spec) DeepCopyInto(out *FederatedIdentityC *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FederatedIdentityCredentialOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -378,6 +428,17 @@ func (in *UserAssignedIdentityOperatorSecrets) DeepCopy() *UserAssignedIdentityO // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdentityOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(UserAssignedIdentityOperatorConfigMaps) @@ -390,6 +451,17 @@ func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdenti (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(UserAssignedIdentityOperatorSecrets) diff --git a/v2/api/managedidentity/v1api20230131/structure.txt b/v2/api/managedidentity/v1api20230131/structure.txt index 94a3faa993f..565a521c06f 100644 --- a/v2/api/managedidentity/v1api20230131/structure.txt +++ b/v2/api/managedidentity/v1api20230131/structure.txt @@ -5,12 +5,15 @@ APIVersion: Enum (1 value) └── "2023-01-31" FederatedIdentityCredential: Resource ├── Owner: UserAssignedIdentity -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── Audiences: string[] │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: Pattern: "^[a-zA-Z0-9]{1}[a-zA-Z0-9-_]{2,119}$" │ ├── Issuer: *string │ ├── IssuerFromConfig: *genruntime.ConfigMapReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Subject: *string │ └── SubjectFromConfig: *genruntime.ConfigMapReference @@ -42,11 +45,13 @@ UserAssignedIdentity: Resource ├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (3 properties) │ │ │ ├── ClientId: *genruntime.ConfigMapDestination │ │ │ ├── PrincipalId: *genruntime.ConfigMapDestination │ │ │ └── TenantId: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── ClientId: *genruntime.SecretDestination │ │ ├── PrincipalId: *genruntime.SecretDestination diff --git a/v2/api/managedidentity/v1api20230131/user_assigned_identity_types_gen.go b/v2/api/managedidentity/v1api20230131/user_assigned_identity_types_gen.go index a404acba45e..92c94a9e465 100644 --- a/v2/api/managedidentity/v1api20230131/user_assigned_identity_types_gen.go +++ b/v2/api/managedidentity/v1api20230131/user_assigned_identity_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -97,6 +98,26 @@ func (identity *UserAssignedIdentity) defaultAzureName() { // defaultImpl applies the code generated defaults to the UserAssignedIdentity resource func (identity *UserAssignedIdentity) defaultImpl() { identity.defaultAzureName() } +var _ configmaps.Exporter = &UserAssignedIdentity{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (identity *UserAssignedIdentity) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &UserAssignedIdentity{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (identity *UserAssignedIdentity) SecretDestinationExpressions() []*core.DestinationExpression { + if identity.Spec.OperatorSpec == nil { + return nil + } + return identity.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &UserAssignedIdentity{} // InitializeSpec initializes the spec for this resource from the given status @@ -274,15 +295,15 @@ func (identity *UserAssignedIdentity) validateConfigMapDestinations() (admission if identity.Spec.OperatorSpec == nil { return nil, nil } - if identity.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - identity.Spec.OperatorSpec.ConfigMaps.ClientId, - identity.Spec.OperatorSpec.ConfigMaps.PrincipalId, - identity.Spec.OperatorSpec.ConfigMaps.TenantId, + var toValidate []*genruntime.ConfigMapDestination + if identity.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + identity.Spec.OperatorSpec.ConfigMaps.ClientId, + identity.Spec.OperatorSpec.ConfigMaps.PrincipalId, + identity.Spec.OperatorSpec.ConfigMaps.TenantId, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(identity, toValidate, identity.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -304,15 +325,15 @@ func (identity *UserAssignedIdentity) validateSecretDestinations() (admission.Wa if identity.Spec.OperatorSpec == nil { return nil, nil } - if identity.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - identity.Spec.OperatorSpec.Secrets.ClientId, - identity.Spec.OperatorSpec.Secrets.PrincipalId, - identity.Spec.OperatorSpec.Secrets.TenantId, + var toValidate []*genruntime.SecretDestination + if identity.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + identity.Spec.OperatorSpec.Secrets.ClientId, + identity.Spec.OperatorSpec.Secrets.PrincipalId, + identity.Spec.OperatorSpec.Secrets.TenantId, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(identity, toValidate, identity.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -921,9 +942,15 @@ func (identity *UserAssignedIdentity_STATUS) AssignProperties_To_UserAssignedIde // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type UserAssignedIdentityOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *UserAssignedIdentityOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *UserAssignedIdentityOperatorSecrets `json:"secrets,omitempty"` } @@ -931,6 +958,24 @@ type UserAssignedIdentityOperatorSpec struct { // AssignProperties_From_UserAssignedIdentityOperatorSpec populates our UserAssignedIdentityOperatorSpec from the provided source UserAssignedIdentityOperatorSpec func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssignedIdentityOperatorSpec(source *storage.UserAssignedIdentityOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap UserAssignedIdentityOperatorConfigMaps @@ -943,6 +988,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_From_UserAssi operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret UserAssignedIdentityOperatorSecrets @@ -964,6 +1027,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.UserAssignedIdentityOperatorConfigMaps @@ -976,6 +1057,24 @@ func (operator *UserAssignedIdentityOperatorSpec) AssignProperties_To_UserAssign destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.UserAssignedIdentityOperatorSecrets diff --git a/v2/api/managedidentity/v1api20230131/zz_generated.deepcopy.go b/v2/api/managedidentity/v1api20230131/zz_generated.deepcopy.go index c60932ff58b..e4bf293f044 100644 --- a/v2/api/managedidentity/v1api20230131/zz_generated.deepcopy.go +++ b/v2/api/managedidentity/v1api20230131/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230131 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *FederatedIdentityCredentialList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopyInto(out *FederatedIdentityCredentialOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FederatedIdentityCredentialOperatorSpec. +func (in *FederatedIdentityCredentialOperatorSpec) DeepCopy() *FederatedIdentityCredentialOperatorSpec { + if in == nil { + return nil + } + out := new(FederatedIdentityCredentialOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FederatedIdentityCredential_STATUS) DeepCopyInto(out *FederatedIdentityCredential_STATUS) { *out = *in @@ -149,6 +187,11 @@ func (in *FederatedIdentityCredential_Spec) DeepCopyInto(out *FederatedIdentityC *out = new(genruntime.ConfigMapReference) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(FederatedIdentityCredentialOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -343,11 +386,33 @@ func (in *UserAssignedIdentityOperatorSecrets) DeepCopy() *UserAssignedIdentityO // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserAssignedIdentityOperatorSpec) DeepCopyInto(out *UserAssignedIdentityOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(UserAssignedIdentityOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(UserAssignedIdentityOperatorSecrets) diff --git a/v2/api/monitor/v1api20230403/account_types_gen.go b/v2/api/monitor/v1api20230403/account_types_gen.go index 0abb97dd8aa..5e819da7e6b 100644 --- a/v2/api/monitor/v1api20230403/account_types_gen.go +++ b/v2/api/monitor/v1api20230403/account_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (account *Account) defaultAzureName() { // defaultImpl applies the code generated defaults to the Account resource func (account *Account) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &Account{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *Account) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Account{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *Account) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Account{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (account *Account) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (account *Account) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference} + return []func() (admission.Warnings, error){account.validateResourceReferences, account.validateOwnerReference, account.validateSecretDestinations, account.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (account *Account) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return account.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return account.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (account *Account) validateConfigMapDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(account, nil, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (account *Account) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (account *Account) validateSecretDestinations() (admission.Warnings, error) { + if account.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(account, nil, account.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (account *Account) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Account) @@ -334,6 +379,10 @@ type Account_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AccountOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -407,6 +456,8 @@ func (account *Account_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe account.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": account.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -495,6 +546,18 @@ func (account *Account_Spec) AssignProperties_From_Account_Spec(source *storage. // Location account.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AccountOperatorSpec + err := operatorSpec.AssignProperties_From_AccountOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AccountOperatorSpec() to populate field OperatorSpec") + } + account.OperatorSpec = &operatorSpec + } else { + account.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -530,6 +593,18 @@ func (account *Account_Spec) AssignProperties_To_Account_Spec(destination *stora // Location destination.Location = genruntime.ClonePointerToString(account.Location) + // OperatorSpec + if account.OperatorSpec != nil { + var operatorSpec storage.AccountOperatorSpec + err := account.OperatorSpec.AssignProperties_To_AccountOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AccountOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = account.OriginalVersion() @@ -1046,6 +1121,110 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-04-03") +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AccountOperatorSpec populates our AccountOperatorSpec from the provided source AccountOperatorSpec +func (operator *AccountOperatorSpec) AssignProperties_From_AccountOperatorSpec(source *storage.AccountOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AccountOperatorSpec populates the provided destination AccountOperatorSpec from our AccountOperatorSpec +func (operator *AccountOperatorSpec) AssignProperties_To_AccountOperatorSpec(destination *storage.AccountOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AzureMonitorWorkspace_ProvisioningState_STATUS string const ( diff --git a/v2/api/monitor/v1api20230403/account_types_gen_test.go b/v2/api/monitor/v1api20230403/account_types_gen_test.go index d94b02160fa..6155c9c4393 100644 --- a/v2/api/monitor/v1api20230403/account_types_gen_test.go +++ b/v2/api/monitor/v1api20230403/account_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForAccount(gens map[string]gopter.Gen) { gens["Status"] = Account_STATUSGenerator() } +func Test_AccountOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AccountOperatorSpec to AccountOperatorSpec via AssignProperties_To_AccountOperatorSpec & AssignProperties_From_AccountOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAccountOperatorSpec, AccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAccountOperatorSpec tests if a specific instance of AccountOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAccountOperatorSpec(subject AccountOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AccountOperatorSpec + err := copied.AssignProperties_To_AccountOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AccountOperatorSpec + err = actual.AssignProperties_From_AccountOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AccountOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AccountOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAccountOperatorSpec, AccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAccountOperatorSpec runs a test to see if a specific instance of AccountOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAccountOperatorSpec(subject AccountOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AccountOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AccountOperatorSpec instances for property testing - lazily instantiated by +// AccountOperatorSpecGenerator() +var accountOperatorSpecGenerator gopter.Gen + +// AccountOperatorSpecGenerator returns a generator of AccountOperatorSpec instances for property testing. +func AccountOperatorSpecGenerator() gopter.Gen { + if accountOperatorSpecGenerator != nil { + return accountOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + accountOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AccountOperatorSpec{}), generators) + + return accountOperatorSpecGenerator +} + func Test_Account_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -383,6 +480,9 @@ func RunJSONSerializationTestForAccount_Spec(subject Account_Spec) string { var account_SpecGenerator gopter.Gen // Account_SpecGenerator returns a generator of Account_Spec instances for property testing. +// We first initialize account_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Account_SpecGenerator() gopter.Gen { if account_SpecGenerator != nil { return account_SpecGenerator @@ -392,6 +492,12 @@ func Account_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAccount_Spec(generators) account_SpecGenerator = gen.Struct(reflect.TypeOf(Account_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAccount_Spec(generators) + AddRelatedPropertyGeneratorsForAccount_Spec(generators) + account_SpecGenerator = gen.Struct(reflect.TypeOf(Account_Spec{}), generators) + return account_SpecGenerator } @@ -405,6 +511,11 @@ func AddIndependentPropertyGeneratorsForAccount_Spec(gens map[string]gopter.Gen) gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForAccount_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAccount_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AccountOperatorSpecGenerator()) +} + func Test_IngestionSettings_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/monitor/v1api20230403/storage/account_types_gen.go b/v2/api/monitor/v1api20230403/storage/account_types_gen.go index 94cd2761444..bba17230c3b 100644 --- a/v2/api/monitor/v1api20230403/storage/account_types_gen.go +++ b/v2/api/monitor/v1api20230403/storage/account_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (account *Account) SetConditions(conditions conditions.Conditions) { account.Status.Conditions = conditions } +var _ configmaps.Exporter = &Account{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *Account) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Account{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *Account) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Account{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type AccountList struct { type Account_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *AccountOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -221,6 +245,14 @@ type APIVersion string const APIVersion_Value = APIVersion("2023-04-03") +// Storage version of v1api20230403.AccountOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AccountOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230403.IngestionSettings_STATUS // Settings for data ingestion type IngestionSettings_STATUS struct { diff --git a/v2/api/monitor/v1api20230403/storage/account_types_gen_test.go b/v2/api/monitor/v1api20230403/storage/account_types_gen_test.go index c6f9246dc3a..685de583f1e 100644 --- a/v2/api/monitor/v1api20230403/storage/account_types_gen_test.go +++ b/v2/api/monitor/v1api20230403/storage/account_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForAccount(gens map[string]gopter.Gen) { gens["Status"] = Account_STATUSGenerator() } +func Test_AccountOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AccountOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAccountOperatorSpec, AccountOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAccountOperatorSpec runs a test to see if a specific instance of AccountOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAccountOperatorSpec(subject AccountOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AccountOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AccountOperatorSpec instances for property testing - lazily instantiated by +// AccountOperatorSpecGenerator() +var accountOperatorSpecGenerator gopter.Gen + +// AccountOperatorSpecGenerator returns a generator of AccountOperatorSpec instances for property testing. +func AccountOperatorSpecGenerator() gopter.Gen { + if accountOperatorSpecGenerator != nil { + return accountOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + accountOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AccountOperatorSpec{}), generators) + + return accountOperatorSpecGenerator +} + func Test_Account_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -208,6 +263,9 @@ func RunJSONSerializationTestForAccount_Spec(subject Account_Spec) string { var account_SpecGenerator gopter.Gen // Account_SpecGenerator returns a generator of Account_Spec instances for property testing. +// We first initialize account_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func Account_SpecGenerator() gopter.Gen { if account_SpecGenerator != nil { return account_SpecGenerator @@ -217,6 +275,12 @@ func Account_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForAccount_Spec(generators) account_SpecGenerator = gen.Struct(reflect.TypeOf(Account_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForAccount_Spec(generators) + AddRelatedPropertyGeneratorsForAccount_Spec(generators) + account_SpecGenerator = gen.Struct(reflect.TypeOf(Account_Spec{}), generators) + return account_SpecGenerator } @@ -231,6 +295,11 @@ func AddIndependentPropertyGeneratorsForAccount_Spec(gens map[string]gopter.Gen) gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForAccount_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForAccount_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AccountOperatorSpecGenerator()) +} + func Test_IngestionSettings_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/monitor/v1api20230403/storage/structure.txt b/v2/api/monitor/v1api20230403/storage/structure.txt index 7c86268151a..71c1bf56c5f 100644 --- a/v2/api/monitor/v1api20230403/storage/structure.txt +++ b/v2/api/monitor/v1api20230403/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2023-04-03" Account: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/monitor/v1api20230403/storage/zz_generated.deepcopy.go b/v2/api/monitor/v1api20230403/storage/zz_generated.deepcopy.go index f09e261f37a..eeae11c468c 100644 --- a/v2/api/monitor/v1api20230403/storage/zz_generated.deepcopy.go +++ b/v2/api/monitor/v1api20230403/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *AccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccountOperatorSpec) DeepCopyInto(out *AccountOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccountOperatorSpec. +func (in *AccountOperatorSpec) DeepCopy() *AccountOperatorSpec { + if in == nil { + return nil + } + out := new(AccountOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Account_STATUS) DeepCopyInto(out *Account_STATUS) { *out = *in @@ -180,6 +225,11 @@ func (in *Account_Spec) DeepCopyInto(out *Account_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AccountOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/monitor/v1api20230403/structure.txt b/v2/api/monitor/v1api20230403/structure.txt index 1b0af3c69d8..93971f3695a 100644 --- a/v2/api/monitor/v1api20230403/structure.txt +++ b/v2/api/monitor/v1api20230403/structure.txt @@ -5,9 +5,12 @@ APIVersion: Enum (1 value) └── "2023-04-03" Account: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" diff --git a/v2/api/monitor/v1api20230403/zz_generated.deepcopy.go b/v2/api/monitor/v1api20230403/zz_generated.deepcopy.go index 319504855a6..4ac59040b92 100644 --- a/v2/api/monitor/v1api20230403/zz_generated.deepcopy.go +++ b/v2/api/monitor/v1api20230403/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230403 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *AccountList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccountOperatorSpec) DeepCopyInto(out *AccountOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccountOperatorSpec. +func (in *AccountOperatorSpec) DeepCopy() *AccountOperatorSpec { + if in == nil { + return nil + } + out := new(AccountOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Account_STATUS) DeepCopyInto(out *Account_STATUS) { *out = *in @@ -173,6 +211,11 @@ func (in *Account_Spec) DeepCopyInto(out *Account_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AccountOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network.frontdoor/v1api20220501/storage/structure.txt b/v2/api/network.frontdoor/v1api20220501/storage/structure.txt index 7fe6c0d721e..db78f904ee9 100644 --- a/v2/api/network.frontdoor/v1api20220501/storage/structure.txt +++ b/v2/api/network.frontdoor/v1api20220501/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-05-01" WebApplicationFirewallPolicy: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── CustomRules: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -58,6 +58,10 @@ WebApplicationFirewallPolicy: Resource │ │ │ ├── RuleSetType: *string │ │ │ └── RuleSetVersion: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PolicySettings: *Object (7 properties) diff --git a/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen.go b/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen.go index f1c81ff1290..c26910b8805 100644 --- a/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen.go +++ b/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *WebApplicationFirewallPolicy) SetConditions(conditions conditions. policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &WebApplicationFirewallPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *WebApplicationFirewallPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WebApplicationFirewallPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *WebApplicationFirewallPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WebApplicationFirewallPolicy{} // AzureName returns the Azure name of the resource @@ -148,12 +171,13 @@ const APIVersion_Value = APIVersion("2022-05-01") type WebApplicationFirewallPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CustomRules *CustomRuleList `json:"customRules,omitempty"` - Etag *string `json:"etag,omitempty"` - Location *string `json:"location,omitempty"` - ManagedRules *ManagedRuleSetList `json:"managedRules,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CustomRules *CustomRuleList `json:"customRules,omitempty"` + Etag *string `json:"etag,omitempty"` + Location *string `json:"location,omitempty"` + ManagedRules *ManagedRuleSetList `json:"managedRules,omitempty"` + OperatorSpec *WebApplicationFirewallPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -314,6 +338,14 @@ type Sku_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220501.WebApplicationFirewallPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebApplicationFirewallPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220501.CustomRule // Defines contents of a web application rule type CustomRule struct { diff --git a/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen_test.go b/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen_test.go index 899e0e0f714..1b0dc62ac91 100644 --- a/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen_test.go +++ b/v2/api/network.frontdoor/v1api20220501/storage/web_application_firewall_policy_types_gen_test.go @@ -1633,6 +1633,61 @@ func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy(gens map[string gens["Status"] = WebApplicationFirewallPolicy_STATUSGenerator() } +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebApplicationFirewallPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec runs a test to see if a specific instance of WebApplicationFirewallPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebApplicationFirewallPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing - lazily instantiated by +// WebApplicationFirewallPolicyOperatorSpecGenerator() +var webApplicationFirewallPolicyOperatorSpecGenerator gopter.Gen + +// WebApplicationFirewallPolicyOperatorSpecGenerator returns a generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing. +func WebApplicationFirewallPolicyOperatorSpecGenerator() gopter.Gen { + if webApplicationFirewallPolicyOperatorSpecGenerator != nil { + return webApplicationFirewallPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webApplicationFirewallPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebApplicationFirewallPolicyOperatorSpec{}), generators) + + return webApplicationFirewallPolicyOperatorSpecGenerator +} + func Test_WebApplicationFirewallPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1803,6 +1858,7 @@ func AddIndependentPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens m func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens map[string]gopter.Gen) { gens["CustomRules"] = gen.PtrOf(CustomRuleListGenerator()) gens["ManagedRules"] = gen.PtrOf(ManagedRuleSetListGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebApplicationFirewallPolicyOperatorSpecGenerator()) gens["PolicySettings"] = gen.PtrOf(PolicySettingsGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/network.frontdoor/v1api20220501/storage/zz_generated.deepcopy.go b/v2/api/network.frontdoor/v1api20220501/storage/zz_generated.deepcopy.go index c37435ff2b8..5e370e213a9 100644 --- a/v2/api/network.frontdoor/v1api20220501/storage/zz_generated.deepcopy.go +++ b/v2/api/network.frontdoor/v1api20220501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1007,6 +1008,50 @@ func (in *WebApplicationFirewallPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopyInto(out *WebApplicationFirewallPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebApplicationFirewallPolicyOperatorSpec. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopy() *WebApplicationFirewallPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(WebApplicationFirewallPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebApplicationFirewallPolicy_STATUS) DeepCopyInto(out *WebApplicationFirewallPolicy_STATUS) { *out = *in @@ -1142,6 +1187,11 @@ func (in *WebApplicationFirewallPolicy_Spec) DeepCopyInto(out *WebApplicationFir *out = new(ManagedRuleSetList) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebApplicationFirewallPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network.frontdoor/v1api20220501/structure.txt b/v2/api/network.frontdoor/v1api20220501/structure.txt index c643ae01b95..05664d18462 100644 --- a/v2/api/network.frontdoor/v1api20220501/structure.txt +++ b/v2/api/network.frontdoor/v1api20220501/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-05-01" WebApplicationFirewallPolicy: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MaxLength: 128 │ ├── CustomRules: *Object (1 property) @@ -129,6 +129,9 @@ WebApplicationFirewallPolicy: Resource │ │ │ └── "Redirect" │ │ ├── RuleSetType: *string │ │ └── RuleSetVersion: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PolicySettings: *Object (6 properties) │ │ ├── CustomBlockResponseBody: Validated<*string> (1 rule) diff --git a/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen.go b/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen.go index 14bb111640c..bf8a7048c97 100644 --- a/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen.go +++ b/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (policy *WebApplicationFirewallPolicy) defaultAzureName() { // defaultImpl applies the code generated defaults to the WebApplicationFirewallPolicy resource func (policy *WebApplicationFirewallPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &WebApplicationFirewallPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *WebApplicationFirewallPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WebApplicationFirewallPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *WebApplicationFirewallPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &WebApplicationFirewallPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (policy *WebApplicationFirewallPolicy) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (policy *WebApplicationFirewallPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (policy *WebApplicationFirewallPolicy) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *WebApplicationFirewallPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (policy *WebApplicationFirewallPolicy) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *WebApplicationFirewallPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *WebApplicationFirewallPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WebApplicationFirewallPolicy) @@ -348,6 +393,10 @@ type WebApplicationFirewallPolicy_Spec struct { // ManagedRules: Describes managed rules inside the policy. ManagedRules *ManagedRuleSetList `json:"managedRules,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WebApplicationFirewallPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -494,6 +543,8 @@ func (policy *WebApplicationFirewallPolicy_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -623,6 +674,18 @@ func (policy *WebApplicationFirewallPolicy_Spec) AssignProperties_From_WebApplic policy.ManagedRules = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WebApplicationFirewallPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -700,6 +763,18 @@ func (policy *WebApplicationFirewallPolicy_Spec) AssignProperties_To_WebApplicat destination.ManagedRules = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.WebApplicationFirewallPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -2649,6 +2724,110 @@ func (sku *Sku_STATUS) AssignProperties_To_Sku_STATUS(destination *storage.Sku_S return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebApplicationFirewallPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec populates our WebApplicationFirewallPolicyOperatorSpec from the provided source WebApplicationFirewallPolicyOperatorSpec +func (operator *WebApplicationFirewallPolicyOperatorSpec) AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(source *storage.WebApplicationFirewallPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec populates the provided destination WebApplicationFirewallPolicyOperatorSpec from our WebApplicationFirewallPolicyOperatorSpec +func (operator *WebApplicationFirewallPolicyOperatorSpec) AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(destination *storage.WebApplicationFirewallPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type WebApplicationFirewallPolicyProperties_ResourceState_STATUS string const ( diff --git a/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen_test.go b/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen_test.go index a9a1bbc3756..2f8d502610f 100644 --- a/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen_test.go +++ b/v2/api/network.frontdoor/v1api20220501/web_application_firewall_policy_types_gen_test.go @@ -2779,6 +2779,103 @@ func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy(gens map[string gens["Status"] = WebApplicationFirewallPolicy_STATUSGenerator() } +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WebApplicationFirewallPolicyOperatorSpec to WebApplicationFirewallPolicyOperatorSpec via AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec & AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec tests if a specific instance of WebApplicationFirewallPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WebApplicationFirewallPolicyOperatorSpec + err := copied.AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WebApplicationFirewallPolicyOperatorSpec + err = actual.AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebApplicationFirewallPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec runs a test to see if a specific instance of WebApplicationFirewallPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebApplicationFirewallPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing - lazily instantiated by +// WebApplicationFirewallPolicyOperatorSpecGenerator() +var webApplicationFirewallPolicyOperatorSpecGenerator gopter.Gen + +// WebApplicationFirewallPolicyOperatorSpecGenerator returns a generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing. +func WebApplicationFirewallPolicyOperatorSpecGenerator() gopter.Gen { + if webApplicationFirewallPolicyOperatorSpecGenerator != nil { + return webApplicationFirewallPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webApplicationFirewallPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebApplicationFirewallPolicyOperatorSpec{}), generators) + + return webApplicationFirewallPolicyOperatorSpecGenerator +} + func Test_WebApplicationFirewallPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3038,6 +3135,7 @@ func AddIndependentPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens m func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens map[string]gopter.Gen) { gens["CustomRules"] = gen.PtrOf(CustomRuleListGenerator()) gens["ManagedRules"] = gen.PtrOf(ManagedRuleSetListGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebApplicationFirewallPolicyOperatorSpecGenerator()) gens["PolicySettings"] = gen.PtrOf(PolicySettingsGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/network.frontdoor/v1api20220501/zz_generated.deepcopy.go b/v2/api/network.frontdoor/v1api20220501/zz_generated.deepcopy.go index d7164bdb177..367544b2b32 100644 --- a/v2/api/network.frontdoor/v1api20220501/zz_generated.deepcopy.go +++ b/v2/api/network.frontdoor/v1api20220501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -846,6 +847,43 @@ func (in *WebApplicationFirewallPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopyInto(out *WebApplicationFirewallPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebApplicationFirewallPolicyOperatorSpec. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopy() *WebApplicationFirewallPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(WebApplicationFirewallPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebApplicationFirewallPolicy_STATUS) DeepCopyInto(out *WebApplicationFirewallPolicy_STATUS) { *out = *in @@ -974,6 +1012,11 @@ func (in *WebApplicationFirewallPolicy_Spec) DeepCopyInto(out *WebApplicationFir *out = new(ManagedRuleSetList) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebApplicationFirewallPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20180501/dns_zone_types_gen.go b/v2/api/network/v1api20180501/dns_zone_types_gen.go index 13135829190..0133ec08537 100644 --- a/v2/api/network/v1api20180501/dns_zone_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zone_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (zone *DnsZone) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZone resource func (zone *DnsZone) defaultImpl() { zone.defaultAzureName() } +var _ configmaps.Exporter = &DnsZone{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (zone *DnsZone) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZone{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (zone *DnsZone) SecretDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZone{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (zone *DnsZone) ValidateUpdate(old runtime.Object) (admission.Warnings, err // createValidations validates the creation of the resource func (zone *DnsZone) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){zone.validateResourceReferences, zone.validateOwnerReference} + return []func() (admission.Warnings, error){zone.validateResourceReferences, zone.validateOwnerReference, zone.validateSecretDestinations, zone.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (zone *DnsZone) updateValidations() []func(old runtime.Object) (admission.W func(old runtime.Object) (admission.Warnings, error) { return zone.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return zone.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return zone.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (zone *DnsZone) validateConfigMapDestinations() (admission.Warnings, error) { + if zone.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(zone, nil, zone.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (zone *DnsZone) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (zone *DnsZone) validateSecretDestinations() (admission.Warnings, error) { + if zone.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(zone, nil, zone.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (zone *DnsZone) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZone) @@ -339,6 +384,10 @@ type DnsZone_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZoneOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -436,6 +485,8 @@ func (zone *DnsZone_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferen zone.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": zone.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -550,6 +601,18 @@ func (zone *DnsZone_Spec) AssignProperties_From_DnsZone_Spec(source *storage.Dns // Location zone.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZoneOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZoneOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZoneOperatorSpec() to populate field OperatorSpec") + } + zone.OperatorSpec = &operatorSpec + } else { + zone.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -621,6 +684,18 @@ func (zone *DnsZone_Spec) AssignProperties_To_DnsZone_Spec(destination *storage. // Location destination.Location = genruntime.ClonePointerToString(zone.Location) + // OperatorSpec + if zone.OperatorSpec != nil { + var operatorSpec storage.DnsZoneOperatorSpec + err := zone.OperatorSpec.AssignProperties_To_DnsZoneOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZoneOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = zone.OriginalVersion() @@ -1163,6 +1238,110 @@ func (zone *DnsZone_STATUS) AssignProperties_To_DnsZone_STATUS(destination *stor return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZoneOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZoneOperatorSpec populates our DnsZoneOperatorSpec from the provided source DnsZoneOperatorSpec +func (operator *DnsZoneOperatorSpec) AssignProperties_From_DnsZoneOperatorSpec(source *storage.DnsZoneOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZoneOperatorSpec populates the provided destination DnsZoneOperatorSpec from our DnsZoneOperatorSpec +func (operator *DnsZoneOperatorSpec) AssignProperties_To_DnsZoneOperatorSpec(destination *storage.DnsZoneOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // A reference to a another resource type SubResource struct { // Reference: Resource Id. diff --git a/v2/api/network/v1api20180501/dns_zone_types_gen_test.go b/v2/api/network/v1api20180501/dns_zone_types_gen_test.go index 4f197082575..edd1be97cbe 100644 --- a/v2/api/network/v1api20180501/dns_zone_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zone_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZone(gens map[string]gopter.Gen) { gens["Status"] = DnsZone_STATUSGenerator() } +func Test_DnsZoneOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZoneOperatorSpec to DnsZoneOperatorSpec via AssignProperties_To_DnsZoneOperatorSpec & AssignProperties_From_DnsZoneOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZoneOperatorSpec, DnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZoneOperatorSpec tests if a specific instance of DnsZoneOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZoneOperatorSpec(subject DnsZoneOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZoneOperatorSpec + err := copied.AssignProperties_To_DnsZoneOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZoneOperatorSpec + err = actual.AssignProperties_From_DnsZoneOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZoneOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZoneOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZoneOperatorSpec, DnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZoneOperatorSpec runs a test to see if a specific instance of DnsZoneOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZoneOperatorSpec(subject DnsZoneOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZoneOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZoneOperatorSpec instances for property testing - lazily instantiated by +// DnsZoneOperatorSpecGenerator() +var dnsZoneOperatorSpecGenerator gopter.Gen + +// DnsZoneOperatorSpecGenerator returns a generator of DnsZoneOperatorSpec instances for property testing. +func DnsZoneOperatorSpecGenerator() gopter.Gen { + if dnsZoneOperatorSpecGenerator != nil { + return dnsZoneOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZoneOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZoneOperatorSpec{}), generators) + + return dnsZoneOperatorSpecGenerator +} + func Test_DnsZone_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -411,6 +508,7 @@ func AddIndependentPropertyGeneratorsForDnsZone_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForDnsZone_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsZone_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsZoneOperatorSpecGenerator()) gens["RegistrationVirtualNetworks"] = gen.SliceOf(SubResourceGenerator()) gens["ResolutionVirtualNetworks"] = gen.SliceOf(SubResourceGenerator()) } diff --git a/v2/api/network/v1api20180501/dns_zones_a_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_a_record_types_gen.go index dabab415144..06a8179707a 100644 --- a/v2/api/network/v1api20180501/dns_zones_a_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_a_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesARecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesARecord resource func (record *DnsZonesARecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesARecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesARecord) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (record *DnsZonesARecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesARecord) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesARecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesARecord) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesARecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesARecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesARecord) @@ -354,6 +399,10 @@ type DnsZonesARecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesARecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -617,6 +666,8 @@ func (record *DnsZonesARecord_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -867,6 +918,18 @@ func (record *DnsZonesARecord_Spec) AssignProperties_From_DnsZonesARecord_Spec(s record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesARecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesARecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesARecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1076,6 +1139,18 @@ func (record *DnsZonesARecord_Spec) AssignProperties_To_DnsZonesARecord_Spec(des destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesARecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesARecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesARecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2160,6 +2235,110 @@ func (record *DnsZonesARecord_STATUS) AssignProperties_To_DnsZonesARecord_STATUS return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesARecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesARecordOperatorSpec populates our DnsZonesARecordOperatorSpec from the provided source DnsZonesARecordOperatorSpec +func (operator *DnsZonesARecordOperatorSpec) AssignProperties_From_DnsZonesARecordOperatorSpec(source *storage.DnsZonesARecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesARecordOperatorSpec populates the provided destination DnsZonesARecordOperatorSpec from our DnsZonesARecordOperatorSpec +func (operator *DnsZonesARecordOperatorSpec) AssignProperties_To_DnsZonesARecordOperatorSpec(destination *storage.DnsZonesARecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesARecord{}, &DnsZonesARecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_a_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_a_record_types_gen_test.go index 6993512f213..86c3a3e93f4 100644 --- a/v2/api/network/v1api20180501/dns_zones_a_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_a_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesARecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesARecord_STATUSGenerator() } +func Test_DnsZonesARecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesARecordOperatorSpec to DnsZonesARecordOperatorSpec via AssignProperties_To_DnsZonesARecordOperatorSpec & AssignProperties_From_DnsZonesARecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesARecordOperatorSpec, DnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesARecordOperatorSpec tests if a specific instance of DnsZonesARecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesARecordOperatorSpec(subject DnsZonesARecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesARecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesARecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesARecordOperatorSpec, DnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesARecordOperatorSpec runs a test to see if a specific instance of DnsZonesARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesARecordOperatorSpec(subject DnsZonesARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesARecordOperatorSpecGenerator() +var dnsZonesARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesARecordOperatorSpecGenerator returns a generator of DnsZonesARecordOperatorSpec instances for property testing. +func DnsZonesARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesARecordOperatorSpecGenerator != nil { + return dnsZonesARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesARecordOperatorSpec{}), generators) + + return dnsZonesARecordOperatorSpecGenerator +} + func Test_DnsZonesARecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -425,6 +522,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesARecord_Spec(gens map[string]gopter. gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen.go index 26be732ce90..267b9431caa 100644 --- a/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesAAAARecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesAAAARecord resource func (record *DnsZonesAAAARecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesAAAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesAAAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesAAAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesAAAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesAAAARecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesAAAARecord) ValidateUpdate(old runtime.Object) (admission. // createValidations validates the creation of the resource func (record *DnsZonesAAAARecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesAAAARecord) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesAAAARecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesAAAARecord) validateResourceReferences() (admission.Warnin return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesAAAARecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesAAAARecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesAAAARecord) @@ -351,6 +396,10 @@ type DnsZonesAAAARecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesAAAARecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesAAAARecord_Spec) PopulateFromARM(owner genruntime.Arbitrar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesAAAARecord_Spec) AssignProperties_From_DnsZonesAAAARecord_ record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesAAAARecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesAAAARecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesAAAARecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesAAAARecord_Spec) AssignProperties_To_DnsZonesAAAARecord_Sp destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesAAAARecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesAAAARecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesAAAARecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2786,6 +2861,110 @@ func (record *CnameRecord_STATUS) AssignProperties_To_CnameRecord_STATUS(destina return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesAAAARecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesAAAARecordOperatorSpec populates our DnsZonesAAAARecordOperatorSpec from the provided source DnsZonesAAAARecordOperatorSpec +func (operator *DnsZonesAAAARecordOperatorSpec) AssignProperties_From_DnsZonesAAAARecordOperatorSpec(source *storage.DnsZonesAAAARecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesAAAARecordOperatorSpec populates the provided destination DnsZonesAAAARecordOperatorSpec from our DnsZonesAAAARecordOperatorSpec +func (operator *DnsZonesAAAARecordOperatorSpec) AssignProperties_To_DnsZonesAAAARecordOperatorSpec(destination *storage.DnsZonesAAAARecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An MX record. type MxRecord struct { // Exchange: The domain name of the mail host for this MX record. diff --git a/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen_test.go index 6dc97b37b95..15e888801fd 100644 --- a/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_aaaa_record_types_gen_test.go @@ -984,6 +984,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesAAAARecord(gens map[string]gopter.Ge gens["Status"] = DnsZonesAAAARecord_STATUSGenerator() } +func Test_DnsZonesAAAARecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesAAAARecordOperatorSpec to DnsZonesAAAARecordOperatorSpec via AssignProperties_To_DnsZonesAAAARecordOperatorSpec & AssignProperties_From_DnsZonesAAAARecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesAAAARecordOperatorSpec, DnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesAAAARecordOperatorSpec tests if a specific instance of DnsZonesAAAARecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesAAAARecordOperatorSpec(subject DnsZonesAAAARecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesAAAARecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesAAAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesAAAARecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesAAAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesAAAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesAAAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec, DnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec runs a test to see if a specific instance of DnsZonesAAAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec(subject DnsZonesAAAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesAAAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesAAAARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesAAAARecordOperatorSpecGenerator() +var dnsZonesAAAARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesAAAARecordOperatorSpecGenerator returns a generator of DnsZonesAAAARecordOperatorSpec instances for property testing. +func DnsZonesAAAARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesAAAARecordOperatorSpecGenerator != nil { + return dnsZonesAAAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesAAAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesAAAARecordOperatorSpec{}), generators) + + return dnsZonesAAAARecordOperatorSpecGenerator +} + func Test_DnsZonesAAAARecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1244,6 +1341,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesAAAARecord_Spec(gens map[string]gopt gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesAAAARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen.go index df412c53c97..19ea3e4696d 100644 --- a/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesCAARecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesCAARecord resource func (record *DnsZonesCAARecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesCAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesCAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesCAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesCAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesCAARecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesCAARecord) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (record *DnsZonesCAARecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesCAARecord) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesCAARecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesCAARecord) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesCAARecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesCAARecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesCAARecord) @@ -351,6 +396,10 @@ type DnsZonesCAARecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesCAARecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesCAARecord_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesCAARecord_Spec) AssignProperties_From_DnsZonesCAARecord_Sp record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesCAARecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesCAARecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesCAARecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesCAARecord_Spec) AssignProperties_To_DnsZonesCAARecord_Spec destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesCAARecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesCAARecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesCAARecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesCAARecord_STATUS) AssignProperties_To_DnsZonesCAARecord_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesCAARecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesCAARecordOperatorSpec populates our DnsZonesCAARecordOperatorSpec from the provided source DnsZonesCAARecordOperatorSpec +func (operator *DnsZonesCAARecordOperatorSpec) AssignProperties_From_DnsZonesCAARecordOperatorSpec(source *storage.DnsZonesCAARecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesCAARecordOperatorSpec populates the provided destination DnsZonesCAARecordOperatorSpec from our DnsZonesCAARecordOperatorSpec +func (operator *DnsZonesCAARecordOperatorSpec) AssignProperties_To_DnsZonesCAARecordOperatorSpec(destination *storage.DnsZonesCAARecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesCAARecord{}, &DnsZonesCAARecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen_test.go index 363d15dd8a3..7d1ed801033 100644 --- a/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_caa_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesCAARecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesCAARecord_STATUSGenerator() } +func Test_DnsZonesCAARecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesCAARecordOperatorSpec to DnsZonesCAARecordOperatorSpec via AssignProperties_To_DnsZonesCAARecordOperatorSpec & AssignProperties_From_DnsZonesCAARecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesCAARecordOperatorSpec, DnsZonesCAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesCAARecordOperatorSpec tests if a specific instance of DnsZonesCAARecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesCAARecordOperatorSpec(subject DnsZonesCAARecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesCAARecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesCAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesCAARecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesCAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesCAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesCAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec, DnsZonesCAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec runs a test to see if a specific instance of DnsZonesCAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec(subject DnsZonesCAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesCAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesCAARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesCAARecordOperatorSpecGenerator() +var dnsZonesCAARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesCAARecordOperatorSpecGenerator returns a generator of DnsZonesCAARecordOperatorSpec instances for property testing. +func DnsZonesCAARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesCAARecordOperatorSpecGenerator != nil { + return dnsZonesCAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesCAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesCAARecordOperatorSpec{}), generators) + + return dnsZonesCAARecordOperatorSpecGenerator +} + func Test_DnsZonesCAARecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesCAARecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesCAARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen.go index 398fe6fe973..b307f342ccc 100644 --- a/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesCNAMERecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesCNAMERecord resource func (record *DnsZonesCNAMERecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesCNAMERecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesCNAMERecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesCNAMERecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesCNAMERecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesCNAMERecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesCNAMERecord) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (record *DnsZonesCNAMERecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesCNAMERecord) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesCNAMERecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesCNAMERecord) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesCNAMERecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesCNAMERecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesCNAMERecord) @@ -351,6 +396,10 @@ type DnsZonesCNAMERecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesCNAMERecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesCNAMERecord_Spec) PopulateFromARM(owner genruntime.Arbitra } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesCNAMERecord_Spec) AssignProperties_From_DnsZonesCNAMERecor record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesCNAMERecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesCNAMERecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesCNAMERecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesCNAMERecord_Spec) AssignProperties_To_DnsZonesCNAMERecord_ destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesCNAMERecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesCNAMERecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesCNAMERecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesCNAMERecord_STATUS) AssignProperties_To_DnsZonesCNAMERecor return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesCNAMERecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesCNAMERecordOperatorSpec populates our DnsZonesCNAMERecordOperatorSpec from the provided source DnsZonesCNAMERecordOperatorSpec +func (operator *DnsZonesCNAMERecordOperatorSpec) AssignProperties_From_DnsZonesCNAMERecordOperatorSpec(source *storage.DnsZonesCNAMERecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesCNAMERecordOperatorSpec populates the provided destination DnsZonesCNAMERecordOperatorSpec from our DnsZonesCNAMERecordOperatorSpec +func (operator *DnsZonesCNAMERecordOperatorSpec) AssignProperties_To_DnsZonesCNAMERecordOperatorSpec(destination *storage.DnsZonesCNAMERecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesCNAMERecord{}, &DnsZonesCNAMERecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen_test.go index 46886eaabb3..35ee5cd4994 100644 --- a/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_cname_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesCNAMERecord(gens map[string]gopter.G gens["Status"] = DnsZonesCNAMERecord_STATUSGenerator() } +func Test_DnsZonesCNAMERecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesCNAMERecordOperatorSpec to DnsZonesCNAMERecordOperatorSpec via AssignProperties_To_DnsZonesCNAMERecordOperatorSpec & AssignProperties_From_DnsZonesCNAMERecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesCNAMERecordOperatorSpec, DnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesCNAMERecordOperatorSpec tests if a specific instance of DnsZonesCNAMERecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesCNAMERecordOperatorSpec(subject DnsZonesCNAMERecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesCNAMERecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesCNAMERecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesCNAMERecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesCNAMERecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesCNAMERecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesCNAMERecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec, DnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec runs a test to see if a specific instance of DnsZonesCNAMERecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec(subject DnsZonesCNAMERecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesCNAMERecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesCNAMERecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesCNAMERecordOperatorSpecGenerator() +var dnsZonesCNAMERecordOperatorSpecGenerator gopter.Gen + +// DnsZonesCNAMERecordOperatorSpecGenerator returns a generator of DnsZonesCNAMERecordOperatorSpec instances for property testing. +func DnsZonesCNAMERecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesCNAMERecordOperatorSpecGenerator != nil { + return dnsZonesCNAMERecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesCNAMERecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesCNAMERecordOperatorSpec{}), generators) + + return dnsZonesCNAMERecordOperatorSpecGenerator +} + func Test_DnsZonesCNAMERecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -425,6 +522,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesCNAMERecord_Spec(gens map[string]gop gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesCNAMERecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen.go index 18abff305f4..c5088ebd131 100644 --- a/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesMXRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesMXRecord resource func (record *DnsZonesMXRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesMXRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesMXRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesMXRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesMXRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesMXRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesMXRecord) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (record *DnsZonesMXRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesMXRecord) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesMXRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesMXRecord) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesMXRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesMXRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesMXRecord) @@ -351,6 +396,10 @@ type DnsZonesMXRecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesMXRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesMXRecord_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesMXRecord_Spec) AssignProperties_From_DnsZonesMXRecord_Spec record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesMXRecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesMXRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesMXRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesMXRecord_Spec) AssignProperties_To_DnsZonesMXRecord_Spec(d destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesMXRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesMXRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesMXRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesMXRecord_STATUS) AssignProperties_To_DnsZonesMXRecord_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesMXRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesMXRecordOperatorSpec populates our DnsZonesMXRecordOperatorSpec from the provided source DnsZonesMXRecordOperatorSpec +func (operator *DnsZonesMXRecordOperatorSpec) AssignProperties_From_DnsZonesMXRecordOperatorSpec(source *storage.DnsZonesMXRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesMXRecordOperatorSpec populates the provided destination DnsZonesMXRecordOperatorSpec from our DnsZonesMXRecordOperatorSpec +func (operator *DnsZonesMXRecordOperatorSpec) AssignProperties_To_DnsZonesMXRecordOperatorSpec(destination *storage.DnsZonesMXRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesMXRecord{}, &DnsZonesMXRecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen_test.go index 0985b432dce..001b249c771 100644 --- a/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_mx_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesMXRecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesMXRecord_STATUSGenerator() } +func Test_DnsZonesMXRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesMXRecordOperatorSpec to DnsZonesMXRecordOperatorSpec via AssignProperties_To_DnsZonesMXRecordOperatorSpec & AssignProperties_From_DnsZonesMXRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesMXRecordOperatorSpec, DnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesMXRecordOperatorSpec tests if a specific instance of DnsZonesMXRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesMXRecordOperatorSpec(subject DnsZonesMXRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesMXRecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesMXRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesMXRecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesMXRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesMXRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesMXRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec, DnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec runs a test to see if a specific instance of DnsZonesMXRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec(subject DnsZonesMXRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesMXRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesMXRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesMXRecordOperatorSpecGenerator() +var dnsZonesMXRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesMXRecordOperatorSpecGenerator returns a generator of DnsZonesMXRecordOperatorSpec instances for property testing. +func DnsZonesMXRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesMXRecordOperatorSpecGenerator != nil { + return dnsZonesMXRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesMXRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesMXRecordOperatorSpec{}), generators) + + return dnsZonesMXRecordOperatorSpecGenerator +} + func Test_DnsZonesMXRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesMXRecord_Spec(gens map[string]gopter gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesMXRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen.go index ef1c783aca0..190fcb4ada0 100644 --- a/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesNSRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesNSRecord resource func (record *DnsZonesNSRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesNSRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesNSRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesNSRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesNSRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesNSRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesNSRecord) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (record *DnsZonesNSRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesNSRecord) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesNSRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesNSRecord) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesNSRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesNSRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesNSRecord) @@ -351,6 +396,10 @@ type DnsZonesNSRecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesNSRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesNSRecord_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesNSRecord_Spec) AssignProperties_From_DnsZonesNSRecord_Spec record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesNSRecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesNSRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesNSRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesNSRecord_Spec) AssignProperties_To_DnsZonesNSRecord_Spec(d destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesNSRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesNSRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesNSRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesNSRecord_STATUS) AssignProperties_To_DnsZonesNSRecord_STAT return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesNSRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesNSRecordOperatorSpec populates our DnsZonesNSRecordOperatorSpec from the provided source DnsZonesNSRecordOperatorSpec +func (operator *DnsZonesNSRecordOperatorSpec) AssignProperties_From_DnsZonesNSRecordOperatorSpec(source *storage.DnsZonesNSRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesNSRecordOperatorSpec populates the provided destination DnsZonesNSRecordOperatorSpec from our DnsZonesNSRecordOperatorSpec +func (operator *DnsZonesNSRecordOperatorSpec) AssignProperties_To_DnsZonesNSRecordOperatorSpec(destination *storage.DnsZonesNSRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesNSRecord{}, &DnsZonesNSRecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen_test.go index e7f3876ebea..151460e7f27 100644 --- a/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_ns_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesNSRecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesNSRecord_STATUSGenerator() } +func Test_DnsZonesNSRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesNSRecordOperatorSpec to DnsZonesNSRecordOperatorSpec via AssignProperties_To_DnsZonesNSRecordOperatorSpec & AssignProperties_From_DnsZonesNSRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesNSRecordOperatorSpec, DnsZonesNSRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesNSRecordOperatorSpec tests if a specific instance of DnsZonesNSRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesNSRecordOperatorSpec(subject DnsZonesNSRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesNSRecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesNSRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesNSRecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesNSRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesNSRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesNSRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec, DnsZonesNSRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec runs a test to see if a specific instance of DnsZonesNSRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec(subject DnsZonesNSRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesNSRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesNSRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesNSRecordOperatorSpecGenerator() +var dnsZonesNSRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesNSRecordOperatorSpecGenerator returns a generator of DnsZonesNSRecordOperatorSpec instances for property testing. +func DnsZonesNSRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesNSRecordOperatorSpecGenerator != nil { + return dnsZonesNSRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesNSRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesNSRecordOperatorSpec{}), generators) + + return dnsZonesNSRecordOperatorSpecGenerator +} + func Test_DnsZonesNSRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesNSRecord_Spec(gens map[string]gopter gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesNSRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen.go index 51bfc365dbf..96146194f56 100644 --- a/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesPTRRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesPTRRecord resource func (record *DnsZonesPTRRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesPTRRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesPTRRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesPTRRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesPTRRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesPTRRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesPTRRecord) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (record *DnsZonesPTRRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesPTRRecord) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesPTRRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesPTRRecord) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesPTRRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesPTRRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesPTRRecord) @@ -351,6 +396,10 @@ type DnsZonesPTRRecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesPTRRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesPTRRecord_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesPTRRecord_Spec) AssignProperties_From_DnsZonesPTRRecord_Sp record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesPTRRecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesPTRRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesPTRRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesPTRRecord_Spec) AssignProperties_To_DnsZonesPTRRecord_Spec destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesPTRRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesPTRRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesPTRRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesPTRRecord_STATUS) AssignProperties_To_DnsZonesPTRRecord_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesPTRRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesPTRRecordOperatorSpec populates our DnsZonesPTRRecordOperatorSpec from the provided source DnsZonesPTRRecordOperatorSpec +func (operator *DnsZonesPTRRecordOperatorSpec) AssignProperties_From_DnsZonesPTRRecordOperatorSpec(source *storage.DnsZonesPTRRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesPTRRecordOperatorSpec populates the provided destination DnsZonesPTRRecordOperatorSpec from our DnsZonesPTRRecordOperatorSpec +func (operator *DnsZonesPTRRecordOperatorSpec) AssignProperties_To_DnsZonesPTRRecordOperatorSpec(destination *storage.DnsZonesPTRRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesPTRRecord{}, &DnsZonesPTRRecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen_test.go index 07d2c1b9ccd..7063bd0ec29 100644 --- a/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_ptr_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesPTRRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesPTRRecord_STATUSGenerator() } +func Test_DnsZonesPTRRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesPTRRecordOperatorSpec to DnsZonesPTRRecordOperatorSpec via AssignProperties_To_DnsZonesPTRRecordOperatorSpec & AssignProperties_From_DnsZonesPTRRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesPTRRecordOperatorSpec, DnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesPTRRecordOperatorSpec tests if a specific instance of DnsZonesPTRRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesPTRRecordOperatorSpec(subject DnsZonesPTRRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesPTRRecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesPTRRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesPTRRecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesPTRRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesPTRRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesPTRRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec, DnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec runs a test to see if a specific instance of DnsZonesPTRRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec(subject DnsZonesPTRRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesPTRRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesPTRRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesPTRRecordOperatorSpecGenerator() +var dnsZonesPTRRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesPTRRecordOperatorSpecGenerator returns a generator of DnsZonesPTRRecordOperatorSpec instances for property testing. +func DnsZonesPTRRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesPTRRecordOperatorSpecGenerator != nil { + return dnsZonesPTRRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesPTRRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesPTRRecordOperatorSpec{}), generators) + + return dnsZonesPTRRecordOperatorSpecGenerator +} + func Test_DnsZonesPTRRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesPTRRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesPTRRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen.go index e9031af0150..6a5592f4b5c 100644 --- a/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesSRVRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesSRVRecord resource func (record *DnsZonesSRVRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesSRVRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesSRVRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesSRVRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesSRVRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesSRVRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesSRVRecord) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (record *DnsZonesSRVRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesSRVRecord) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesSRVRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesSRVRecord) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesSRVRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesSRVRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesSRVRecord) @@ -351,6 +396,10 @@ type DnsZonesSRVRecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesSRVRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesSRVRecord_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesSRVRecord_Spec) AssignProperties_From_DnsZonesSRVRecord_Sp record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesSRVRecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesSRVRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesSRVRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesSRVRecord_Spec) AssignProperties_To_DnsZonesSRVRecord_Spec destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesSRVRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesSRVRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesSRVRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesSRVRecord_STATUS) AssignProperties_To_DnsZonesSRVRecord_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesSRVRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesSRVRecordOperatorSpec populates our DnsZonesSRVRecordOperatorSpec from the provided source DnsZonesSRVRecordOperatorSpec +func (operator *DnsZonesSRVRecordOperatorSpec) AssignProperties_From_DnsZonesSRVRecordOperatorSpec(source *storage.DnsZonesSRVRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesSRVRecordOperatorSpec populates the provided destination DnsZonesSRVRecordOperatorSpec from our DnsZonesSRVRecordOperatorSpec +func (operator *DnsZonesSRVRecordOperatorSpec) AssignProperties_To_DnsZonesSRVRecordOperatorSpec(destination *storage.DnsZonesSRVRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesSRVRecord{}, &DnsZonesSRVRecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen_test.go index f33fafea87e..e5ef98f3313 100644 --- a/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_srv_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesSRVRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesSRVRecord_STATUSGenerator() } +func Test_DnsZonesSRVRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesSRVRecordOperatorSpec to DnsZonesSRVRecordOperatorSpec via AssignProperties_To_DnsZonesSRVRecordOperatorSpec & AssignProperties_From_DnsZonesSRVRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesSRVRecordOperatorSpec, DnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesSRVRecordOperatorSpec tests if a specific instance of DnsZonesSRVRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesSRVRecordOperatorSpec(subject DnsZonesSRVRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesSRVRecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesSRVRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesSRVRecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesSRVRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesSRVRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesSRVRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec, DnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec runs a test to see if a specific instance of DnsZonesSRVRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec(subject DnsZonesSRVRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesSRVRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesSRVRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesSRVRecordOperatorSpecGenerator() +var dnsZonesSRVRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesSRVRecordOperatorSpecGenerator returns a generator of DnsZonesSRVRecordOperatorSpec instances for property testing. +func DnsZonesSRVRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesSRVRecordOperatorSpecGenerator != nil { + return dnsZonesSRVRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesSRVRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesSRVRecordOperatorSpec{}), generators) + + return dnsZonesSRVRecordOperatorSpecGenerator +} + func Test_DnsZonesSRVRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesSRVRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesSRVRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen.go b/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen.go index b1251bac615..b2f4e863f5b 100644 --- a/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen.go +++ b/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *DnsZonesTXTRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsZonesTXTRecord resource func (record *DnsZonesTXTRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &DnsZonesTXTRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesTXTRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesTXTRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesTXTRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsZonesTXTRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *DnsZonesTXTRecord) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (record *DnsZonesTXTRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *DnsZonesTXTRecord) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *DnsZonesTXTRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *DnsZonesTXTRecord) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *DnsZonesTXTRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *DnsZonesTXTRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsZonesTXTRecord) @@ -351,6 +396,10 @@ type DnsZonesTXTRecord_Spec struct { // NSRecords: The list of NS records in the record set. NSRecords []NsRecord `json:"NSRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsZonesTXTRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (record *DnsZonesTXTRecord_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -849,6 +900,18 @@ func (record *DnsZonesTXTRecord_Spec) AssignProperties_From_DnsZonesTXTRecord_Sp record.NSRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsZonesTXTRecordOperatorSpec + err := operatorSpec.AssignProperties_From_DnsZonesTXTRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsZonesTXTRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1055,6 +1118,18 @@ func (record *DnsZonesTXTRecord_Spec) AssignProperties_To_DnsZonesTXTRecord_Spec destination.NSRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.DnsZonesTXTRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_DnsZonesTXTRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsZonesTXTRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2136,6 +2211,110 @@ func (record *DnsZonesTXTRecord_STATUS) AssignProperties_To_DnsZonesTXTRecord_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesTXTRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsZonesTXTRecordOperatorSpec populates our DnsZonesTXTRecordOperatorSpec from the provided source DnsZonesTXTRecordOperatorSpec +func (operator *DnsZonesTXTRecordOperatorSpec) AssignProperties_From_DnsZonesTXTRecordOperatorSpec(source *storage.DnsZonesTXTRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsZonesTXTRecordOperatorSpec populates the provided destination DnsZonesTXTRecordOperatorSpec from our DnsZonesTXTRecordOperatorSpec +func (operator *DnsZonesTXTRecordOperatorSpec) AssignProperties_To_DnsZonesTXTRecordOperatorSpec(destination *storage.DnsZonesTXTRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsZonesTXTRecord{}, &DnsZonesTXTRecordList{}) } diff --git a/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen_test.go b/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen_test.go index 0f753a70b36..89d55ad802d 100644 --- a/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/dns_zones_txt_record_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsZonesTXTRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesTXTRecord_STATUSGenerator() } +func Test_DnsZonesTXTRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsZonesTXTRecordOperatorSpec to DnsZonesTXTRecordOperatorSpec via AssignProperties_To_DnsZonesTXTRecordOperatorSpec & AssignProperties_From_DnsZonesTXTRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsZonesTXTRecordOperatorSpec, DnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsZonesTXTRecordOperatorSpec tests if a specific instance of DnsZonesTXTRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsZonesTXTRecordOperatorSpec(subject DnsZonesTXTRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsZonesTXTRecordOperatorSpec + err := copied.AssignProperties_To_DnsZonesTXTRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsZonesTXTRecordOperatorSpec + err = actual.AssignProperties_From_DnsZonesTXTRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsZonesTXTRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesTXTRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec, DnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec runs a test to see if a specific instance of DnsZonesTXTRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec(subject DnsZonesTXTRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesTXTRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesTXTRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesTXTRecordOperatorSpecGenerator() +var dnsZonesTXTRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesTXTRecordOperatorSpecGenerator returns a generator of DnsZonesTXTRecordOperatorSpec instances for property testing. +func DnsZonesTXTRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesTXTRecordOperatorSpecGenerator != nil { + return dnsZonesTXTRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesTXTRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesTXTRecordOperatorSpec{}), generators) + + return dnsZonesTXTRecordOperatorSpecGenerator +} + func Test_DnsZonesTXTRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -424,6 +521,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesTXTRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesTXTRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zone_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zone_types_gen.go index 1d5aee376d9..4f0bc130f81 100644 --- a/v2/api/network/v1api20180501/storage/dns_zone_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zone_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20200601/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (zone *DnsZone) SetConditions(conditions conditions.Conditions) { zone.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZone{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (zone *DnsZone) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZone{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (zone *DnsZone) SecretDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZone{} // AzureName returns the Azure name of the resource @@ -149,9 +172,10 @@ const APIVersion_Value = APIVersion("2018-05-01") type DnsZone_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DnsZoneOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -224,6 +248,14 @@ func (zone *DnsZone_STATUS) ConvertStatusTo(destination genruntime.ConvertibleSt return destination.ConvertStatusFrom(zone) } +// Storage version of v1api20180501.DnsZoneOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZoneOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20180501.SubResource // A reference to a another resource type SubResource struct { diff --git a/v2/api/network/v1api20180501/storage/dns_zone_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zone_types_gen_test.go index 44295c7e0a5..809cd900029 100644 --- a/v2/api/network/v1api20180501/storage/dns_zone_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zone_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsZone(gens map[string]gopter.Gen) { gens["Status"] = DnsZone_STATUSGenerator() } +func Test_DnsZoneOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZoneOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZoneOperatorSpec, DnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZoneOperatorSpec runs a test to see if a specific instance of DnsZoneOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZoneOperatorSpec(subject DnsZoneOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZoneOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZoneOperatorSpec instances for property testing - lazily instantiated by +// DnsZoneOperatorSpecGenerator() +var dnsZoneOperatorSpecGenerator gopter.Gen + +// DnsZoneOperatorSpecGenerator returns a generator of DnsZoneOperatorSpec instances for property testing. +func DnsZoneOperatorSpecGenerator() gopter.Gen { + if dnsZoneOperatorSpecGenerator != nil { + return dnsZoneOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZoneOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZoneOperatorSpec{}), generators) + + return dnsZoneOperatorSpecGenerator +} + func Test_DnsZone_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -243,6 +298,7 @@ func AddIndependentPropertyGeneratorsForDnsZone_Spec(gens map[string]gopter.Gen) // AddRelatedPropertyGeneratorsForDnsZone_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsZone_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsZoneOperatorSpecGenerator()) gens["RegistrationVirtualNetworks"] = gen.SliceOf(SubResourceGenerator()) gens["ResolutionVirtualNetworks"] = gen.SliceOf(SubResourceGenerator()) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen.go index 4a543d64739..ea2fc361e67 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesARecord) SetConditions(conditions conditions.Conditions) { record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesARecord{} // AzureName returns the Azure name of the resource @@ -145,14 +168,15 @@ type DnsZonesARecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - Etag *string `json:"etag,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + Etag *string `json:"etag,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesARecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -233,6 +257,14 @@ func (record *DnsZonesARecord_STATUS) ConvertStatusTo(destination genruntime.Con return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesARecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesARecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesARecord{}, &DnsZonesARecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen_test.go index 5429ff2f0ee..ec331b12364 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_a_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesARecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesARecord_STATUSGenerator() } +func Test_DnsZonesARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesARecordOperatorSpec, DnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesARecordOperatorSpec runs a test to see if a specific instance of DnsZonesARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesARecordOperatorSpec(subject DnsZonesARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesARecordOperatorSpecGenerator() +var dnsZonesARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesARecordOperatorSpecGenerator returns a generator of DnsZonesARecordOperatorSpec instances for property testing. +func DnsZonesARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesARecordOperatorSpecGenerator != nil { + return dnsZonesARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesARecordOperatorSpec{}), generators) + + return dnsZonesARecordOperatorSpecGenerator +} + func Test_DnsZonesARecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -256,6 +311,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesARecord_Spec(gens map[string]gopter. gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen.go index 350f6750a94..0e701d73e8b 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20200601/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (record *DnsZonesAAAARecord) SetConditions(conditions conditions.Conditions record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesAAAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesAAAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesAAAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesAAAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesAAAARecord{} // AzureName returns the Azure name of the resource @@ -146,13 +169,14 @@ type DnsZonesAAAARecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesAAAARecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -629,6 +653,14 @@ func (record *CnameRecord_STATUS) AssignProperties_To_CnameRecord_STATUS(destina return nil } +// Storage version of v1api20180501.DnsZonesAAAARecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesAAAARecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20180501.MxRecord // An MX record. type MxRecord struct { diff --git a/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen_test.go index 7aa0910f2a3..ee58f5dc78f 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_aaaa_record_types_gen_test.go @@ -815,6 +815,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesAAAARecord(gens map[string]gopter.Ge gens["Status"] = DnsZonesAAAARecord_STATUSGenerator() } +func Test_DnsZonesAAAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesAAAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec, DnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec runs a test to see if a specific instance of DnsZonesAAAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesAAAARecordOperatorSpec(subject DnsZonesAAAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesAAAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesAAAARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesAAAARecordOperatorSpecGenerator() +var dnsZonesAAAARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesAAAARecordOperatorSpecGenerator returns a generator of DnsZonesAAAARecordOperatorSpec instances for property testing. +func DnsZonesAAAARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesAAAARecordOperatorSpecGenerator != nil { + return dnsZonesAAAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesAAAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesAAAARecordOperatorSpec{}), generators) + + return dnsZonesAAAARecordOperatorSpecGenerator +} + func Test_DnsZonesAAAARecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -992,6 +1047,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesAAAARecord_Spec(gens map[string]gopt gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesAAAARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen.go index 8b3ad60e324..decf39bc0b5 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesCAARecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesCAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesCAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesCAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesCAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesCAARecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesCAARecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesCAARecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesCAARecord_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesCAARecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesCAARecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesCAARecord{}, &DnsZonesCAARecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen_test.go index 3ec4857b065..8355f15569c 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_caa_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesCAARecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesCAARecord_STATUSGenerator() } +func Test_DnsZonesCAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesCAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec, DnsZonesCAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec runs a test to see if a specific instance of DnsZonesCAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesCAARecordOperatorSpec(subject DnsZonesCAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesCAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesCAARecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesCAARecordOperatorSpecGenerator() +var dnsZonesCAARecordOperatorSpecGenerator gopter.Gen + +// DnsZonesCAARecordOperatorSpecGenerator returns a generator of DnsZonesCAARecordOperatorSpec instances for property testing. +func DnsZonesCAARecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesCAARecordOperatorSpecGenerator != nil { + return dnsZonesCAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesCAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesCAARecordOperatorSpec{}), generators) + + return dnsZonesCAARecordOperatorSpecGenerator +} + func Test_DnsZonesCAARecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesCAARecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesCAARecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen.go index 17e5e62f71e..ef5d04ad0ad 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesCNAMERecord) SetConditions(conditions conditions.Condition record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesCNAMERecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesCNAMERecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesCNAMERecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesCNAMERecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesCNAMERecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesCNAMERecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesCNAMERecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesCNAMERecord_STATUS) ConvertStatusTo(destination genruntime return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesCNAMERecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesCNAMERecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesCNAMERecord{}, &DnsZonesCNAMERecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen_test.go index 15c2cdac669..462c7767a27 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_cname_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesCNAMERecord(gens map[string]gopter.G gens["Status"] = DnsZonesCNAMERecord_STATUSGenerator() } +func Test_DnsZonesCNAMERecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesCNAMERecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec, DnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec runs a test to see if a specific instance of DnsZonesCNAMERecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesCNAMERecordOperatorSpec(subject DnsZonesCNAMERecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesCNAMERecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesCNAMERecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesCNAMERecordOperatorSpecGenerator() +var dnsZonesCNAMERecordOperatorSpecGenerator gopter.Gen + +// DnsZonesCNAMERecordOperatorSpecGenerator returns a generator of DnsZonesCNAMERecordOperatorSpec instances for property testing. +func DnsZonesCNAMERecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesCNAMERecordOperatorSpecGenerator != nil { + return dnsZonesCNAMERecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesCNAMERecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesCNAMERecordOperatorSpec{}), generators) + + return dnsZonesCNAMERecordOperatorSpecGenerator +} + func Test_DnsZonesCNAMERecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -256,6 +311,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesCNAMERecord_Spec(gens map[string]gop gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesCNAMERecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen.go index 635f262c71e..81d6a5eb396 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesMXRecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesMXRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesMXRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesMXRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesMXRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesMXRecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesMXRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesMXRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesMXRecord_STATUS) ConvertStatusTo(destination genruntime.Co return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesMXRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesMXRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesMXRecord{}, &DnsZonesMXRecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen_test.go index 694965fa862..2e849abe9cb 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_mx_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesMXRecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesMXRecord_STATUSGenerator() } +func Test_DnsZonesMXRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesMXRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec, DnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec runs a test to see if a specific instance of DnsZonesMXRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesMXRecordOperatorSpec(subject DnsZonesMXRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesMXRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesMXRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesMXRecordOperatorSpecGenerator() +var dnsZonesMXRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesMXRecordOperatorSpecGenerator returns a generator of DnsZonesMXRecordOperatorSpec instances for property testing. +func DnsZonesMXRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesMXRecordOperatorSpecGenerator != nil { + return dnsZonesMXRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesMXRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesMXRecordOperatorSpec{}), generators) + + return dnsZonesMXRecordOperatorSpecGenerator +} + func Test_DnsZonesMXRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesMXRecord_Spec(gens map[string]gopter gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesMXRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen.go index 0865eff8e9e..25730ec0574 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesNSRecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesNSRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesNSRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesNSRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesNSRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesNSRecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesNSRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesNSRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesNSRecord_STATUS) ConvertStatusTo(destination genruntime.Co return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesNSRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesNSRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesNSRecord{}, &DnsZonesNSRecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen_test.go index 42696b486ea..3e9b5b66c3f 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_ns_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesNSRecord(gens map[string]gopter.Gen) gens["Status"] = DnsZonesNSRecord_STATUSGenerator() } +func Test_DnsZonesNSRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesNSRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec, DnsZonesNSRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec runs a test to see if a specific instance of DnsZonesNSRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesNSRecordOperatorSpec(subject DnsZonesNSRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesNSRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesNSRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesNSRecordOperatorSpecGenerator() +var dnsZonesNSRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesNSRecordOperatorSpecGenerator returns a generator of DnsZonesNSRecordOperatorSpec instances for property testing. +func DnsZonesNSRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesNSRecordOperatorSpecGenerator != nil { + return dnsZonesNSRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesNSRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesNSRecordOperatorSpec{}), generators) + + return dnsZonesNSRecordOperatorSpecGenerator +} + func Test_DnsZonesNSRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesNSRecord_Spec(gens map[string]gopter gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesNSRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen.go index 4dc6faa102b..6529d337a83 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesPTRRecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesPTRRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesPTRRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesPTRRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesPTRRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesPTRRecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesPTRRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesPTRRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesPTRRecord_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesPTRRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesPTRRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesPTRRecord{}, &DnsZonesPTRRecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen_test.go index 2fa8cbf7072..7ede0b6f16c 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_ptr_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesPTRRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesPTRRecord_STATUSGenerator() } +func Test_DnsZonesPTRRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesPTRRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec, DnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec runs a test to see if a specific instance of DnsZonesPTRRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesPTRRecordOperatorSpec(subject DnsZonesPTRRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesPTRRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesPTRRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesPTRRecordOperatorSpecGenerator() +var dnsZonesPTRRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesPTRRecordOperatorSpecGenerator returns a generator of DnsZonesPTRRecordOperatorSpec instances for property testing. +func DnsZonesPTRRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesPTRRecordOperatorSpecGenerator != nil { + return dnsZonesPTRRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesPTRRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesPTRRecordOperatorSpec{}), generators) + + return dnsZonesPTRRecordOperatorSpecGenerator +} + func Test_DnsZonesPTRRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesPTRRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesPTRRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen.go index a200856e598..9853e847ef5 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesSRVRecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesSRVRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesSRVRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesSRVRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesSRVRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesSRVRecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesSRVRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesSRVRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesSRVRecord_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesSRVRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesSRVRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesSRVRecord{}, &DnsZonesSRVRecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen_test.go index a458158278f..1a1f4e62742 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_srv_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesSRVRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesSRVRecord_STATUSGenerator() } +func Test_DnsZonesSRVRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesSRVRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec, DnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec runs a test to see if a specific instance of DnsZonesSRVRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesSRVRecordOperatorSpec(subject DnsZonesSRVRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesSRVRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesSRVRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesSRVRecordOperatorSpecGenerator() +var dnsZonesSRVRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesSRVRecordOperatorSpecGenerator returns a generator of DnsZonesSRVRecordOperatorSpec instances for property testing. +func DnsZonesSRVRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesSRVRecordOperatorSpecGenerator != nil { + return dnsZonesSRVRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesSRVRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesSRVRecordOperatorSpec{}), generators) + + return dnsZonesSRVRecordOperatorSpecGenerator +} + func Test_DnsZonesSRVRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesSRVRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesSRVRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen.go b/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen.go index 95dd42fe6c3..00033afab28 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *DnsZonesTXTRecord) SetConditions(conditions conditions.Conditions) record.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsZonesTXTRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *DnsZonesTXTRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsZonesTXTRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *DnsZonesTXTRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsZonesTXTRecord{} // AzureName returns the Azure name of the resource @@ -145,13 +168,14 @@ type DnsZonesTXTRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - CaaRecords []CaaRecord `json:"caaRecords,omitempty"` - MXRecords []MxRecord `json:"MXRecords,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - NSRecords []NsRecord `json:"NSRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` + CaaRecords []CaaRecord `json:"caaRecords,omitempty"` + MXRecords []MxRecord `json:"MXRecords,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + NSRecords []NsRecord `json:"NSRecords,omitempty"` + OperatorSpec *DnsZonesTXTRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (record *DnsZonesTXTRecord_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(record) } +// Storage version of v1api20180501.DnsZonesTXTRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsZonesTXTRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsZonesTXTRecord{}, &DnsZonesTXTRecordList{}) } diff --git a/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen_test.go b/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen_test.go index 877d96a4e1c..01904beb13c 100644 --- a/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen_test.go +++ b/v2/api/network/v1api20180501/storage/dns_zones_txt_record_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsZonesTXTRecord(gens map[string]gopter.Gen gens["Status"] = DnsZonesTXTRecord_STATUSGenerator() } +func Test_DnsZonesTXTRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsZonesTXTRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec, DnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec runs a test to see if a specific instance of DnsZonesTXTRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsZonesTXTRecordOperatorSpec(subject DnsZonesTXTRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsZonesTXTRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsZonesTXTRecordOperatorSpec instances for property testing - lazily instantiated by +// DnsZonesTXTRecordOperatorSpecGenerator() +var dnsZonesTXTRecordOperatorSpecGenerator gopter.Gen + +// DnsZonesTXTRecordOperatorSpecGenerator returns a generator of DnsZonesTXTRecordOperatorSpec instances for property testing. +func DnsZonesTXTRecordOperatorSpecGenerator() gopter.Gen { + if dnsZonesTXTRecordOperatorSpecGenerator != nil { + return dnsZonesTXTRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsZonesTXTRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsZonesTXTRecordOperatorSpec{}), generators) + + return dnsZonesTXTRecordOperatorSpecGenerator +} + func Test_DnsZonesTXTRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,6 +310,7 @@ func AddRelatedPropertyGeneratorsForDnsZonesTXTRecord_Spec(gens map[string]gopte gens["CaaRecords"] = gen.SliceOf(CaaRecordGenerator()) gens["MXRecords"] = gen.SliceOf(MxRecordGenerator()) gens["NSRecords"] = gen.SliceOf(NsRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsZonesTXTRecordOperatorSpecGenerator()) gens["PTRRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SOARecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SRVRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20180501/storage/structure.txt b/v2/api/network/v1api20180501/storage/structure.txt index 454cc77a1d4..a7d02a6cbb1 100644 --- a/v2/api/network/v1api20180501/storage/structure.txt +++ b/v2/api/network/v1api20180501/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2018-05-01" DnsZone: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -41,7 +45,7 @@ DnsZone: Resource └── ZoneType: *string DnsZonesAAAARecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -65,6 +69,10 @@ DnsZonesAAAARecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -151,7 +159,7 @@ DnsZonesAAAARecord: Resource └── Type: *string DnsZonesARecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -176,6 +184,10 @@ DnsZonesARecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -262,7 +274,7 @@ DnsZonesARecord: Resource └── Type: *string DnsZonesCAARecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -286,6 +298,10 @@ DnsZonesCAARecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -372,7 +388,7 @@ DnsZonesCAARecord: Resource └── Type: *string DnsZonesCNAMERecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -396,6 +412,10 @@ DnsZonesCNAMERecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -482,7 +502,7 @@ DnsZonesCNAMERecord: Resource └── Type: *string DnsZonesMXRecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -506,6 +526,10 @@ DnsZonesMXRecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -592,7 +616,7 @@ DnsZonesMXRecord: Resource └── Type: *string DnsZonesNSRecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -616,6 +640,10 @@ DnsZonesNSRecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -702,7 +730,7 @@ DnsZonesNSRecord: Resource └── Type: *string DnsZonesPTRRecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -726,6 +754,10 @@ DnsZonesPTRRecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -812,7 +844,7 @@ DnsZonesPTRRecord: Resource └── Type: *string DnsZonesSRVRecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -836,6 +868,10 @@ DnsZonesSRVRecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] @@ -922,7 +958,7 @@ DnsZonesSRVRecord: Resource └── Type: *string DnsZonesTXTRecord: Resource ├── Owner: network/v1api20180501.DnsZone -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AAAARecords: Object (2 properties)[] │ │ ├── Ipv6Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -946,6 +982,10 @@ DnsZonesTXTRecord: Resource │ ├── NSRecords: Object (2 properties)[] │ │ ├── Nsdname: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (2 properties)[] diff --git a/v2/api/network/v1api20180501/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20180501/storage/zz_generated.deepcopy.go index edeecfccd39..c7b850ef97b 100644 --- a/v2/api/network/v1api20180501/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20180501/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -310,6 +311,50 @@ func (in *DnsZoneList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZoneOperatorSpec) DeepCopyInto(out *DnsZoneOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZoneOperatorSpec. +func (in *DnsZoneOperatorSpec) DeepCopy() *DnsZoneOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZoneOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZone_STATUS) DeepCopyInto(out *DnsZone_STATUS) { *out = *in @@ -418,6 +463,11 @@ func (in *DnsZone_Spec) DeepCopyInto(out *DnsZone_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZoneOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -527,6 +577,50 @@ func (in *DnsZonesAAAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesAAAARecordOperatorSpec) DeepCopyInto(out *DnsZonesAAAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesAAAARecordOperatorSpec. +func (in *DnsZonesAAAARecordOperatorSpec) DeepCopy() *DnsZonesAAAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesAAAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesAAAARecord_STATUS) DeepCopyInto(out *DnsZonesAAAARecord_STATUS) { *out = *in @@ -719,6 +813,11 @@ func (in *DnsZonesAAAARecord_Spec) DeepCopyInto(out *DnsZonesAAAARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesAAAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -838,6 +937,50 @@ func (in *DnsZonesARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesARecordOperatorSpec) DeepCopyInto(out *DnsZonesARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesARecordOperatorSpec. +func (in *DnsZonesARecordOperatorSpec) DeepCopy() *DnsZonesARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesARecord_STATUS) DeepCopyInto(out *DnsZonesARecord_STATUS) { *out = *in @@ -1035,6 +1178,11 @@ func (in *DnsZonesARecord_Spec) DeepCopyInto(out *DnsZonesARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1154,6 +1302,50 @@ func (in *DnsZonesCAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesCAARecordOperatorSpec) DeepCopyInto(out *DnsZonesCAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesCAARecordOperatorSpec. +func (in *DnsZonesCAARecordOperatorSpec) DeepCopy() *DnsZonesCAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesCAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesCAARecord_STATUS) DeepCopyInto(out *DnsZonesCAARecord_STATUS) { *out = *in @@ -1346,6 +1538,11 @@ func (in *DnsZonesCAARecord_Spec) DeepCopyInto(out *DnsZonesCAARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesCAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1465,6 +1662,50 @@ func (in *DnsZonesCNAMERecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesCNAMERecordOperatorSpec) DeepCopyInto(out *DnsZonesCNAMERecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesCNAMERecordOperatorSpec. +func (in *DnsZonesCNAMERecordOperatorSpec) DeepCopy() *DnsZonesCNAMERecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesCNAMERecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesCNAMERecord_STATUS) DeepCopyInto(out *DnsZonesCNAMERecord_STATUS) { *out = *in @@ -1657,6 +1898,11 @@ func (in *DnsZonesCNAMERecord_Spec) DeepCopyInto(out *DnsZonesCNAMERecord_Spec) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesCNAMERecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1776,6 +2022,50 @@ func (in *DnsZonesMXRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesMXRecordOperatorSpec) DeepCopyInto(out *DnsZonesMXRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesMXRecordOperatorSpec. +func (in *DnsZonesMXRecordOperatorSpec) DeepCopy() *DnsZonesMXRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesMXRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesMXRecord_STATUS) DeepCopyInto(out *DnsZonesMXRecord_STATUS) { *out = *in @@ -1968,6 +2258,11 @@ func (in *DnsZonesMXRecord_Spec) DeepCopyInto(out *DnsZonesMXRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesMXRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2087,6 +2382,50 @@ func (in *DnsZonesNSRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesNSRecordOperatorSpec) DeepCopyInto(out *DnsZonesNSRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesNSRecordOperatorSpec. +func (in *DnsZonesNSRecordOperatorSpec) DeepCopy() *DnsZonesNSRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesNSRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesNSRecord_STATUS) DeepCopyInto(out *DnsZonesNSRecord_STATUS) { *out = *in @@ -2279,6 +2618,11 @@ func (in *DnsZonesNSRecord_Spec) DeepCopyInto(out *DnsZonesNSRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesNSRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2398,6 +2742,50 @@ func (in *DnsZonesPTRRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesPTRRecordOperatorSpec) DeepCopyInto(out *DnsZonesPTRRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesPTRRecordOperatorSpec. +func (in *DnsZonesPTRRecordOperatorSpec) DeepCopy() *DnsZonesPTRRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesPTRRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesPTRRecord_STATUS) DeepCopyInto(out *DnsZonesPTRRecord_STATUS) { *out = *in @@ -2590,6 +2978,11 @@ func (in *DnsZonesPTRRecord_Spec) DeepCopyInto(out *DnsZonesPTRRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesPTRRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2709,6 +3102,50 @@ func (in *DnsZonesSRVRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesSRVRecordOperatorSpec) DeepCopyInto(out *DnsZonesSRVRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesSRVRecordOperatorSpec. +func (in *DnsZonesSRVRecordOperatorSpec) DeepCopy() *DnsZonesSRVRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesSRVRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesSRVRecord_STATUS) DeepCopyInto(out *DnsZonesSRVRecord_STATUS) { *out = *in @@ -2901,6 +3338,11 @@ func (in *DnsZonesSRVRecord_Spec) DeepCopyInto(out *DnsZonesSRVRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesSRVRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3020,6 +3462,50 @@ func (in *DnsZonesTXTRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesTXTRecordOperatorSpec) DeepCopyInto(out *DnsZonesTXTRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesTXTRecordOperatorSpec. +func (in *DnsZonesTXTRecordOperatorSpec) DeepCopy() *DnsZonesTXTRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesTXTRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesTXTRecord_STATUS) DeepCopyInto(out *DnsZonesTXTRecord_STATUS) { *out = *in @@ -3212,6 +3698,11 @@ func (in *DnsZonesTXTRecord_Spec) DeepCopyInto(out *DnsZonesTXTRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesTXTRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20180501/structure.txt b/v2/api/network/v1api20180501/structure.txt index 946ddc66a8a..7406e3c96ae 100644 --- a/v2/api/network/v1api20180501/structure.txt +++ b/v2/api/network/v1api20180501/structure.txt @@ -5,9 +5,12 @@ APIVersion: Enum (1 value) └── "2018-05-01" DnsZone: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RegistrationVirtualNetworks: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference @@ -38,7 +41,7 @@ DnsZone: Resource └── "Public" DnsZonesAAAARecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -56,6 +59,9 @@ DnsZonesAAAARecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -123,7 +129,7 @@ DnsZonesAAAARecord: Resource └── Type: *string DnsZonesARecord: Resource ├── Owner: DnsZone -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -142,6 +148,9 @@ DnsZonesARecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -209,7 +218,7 @@ DnsZonesARecord: Resource └── Type: *string DnsZonesCAARecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -227,6 +236,9 @@ DnsZonesCAARecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -294,7 +306,7 @@ DnsZonesCAARecord: Resource └── Type: *string DnsZonesCNAMERecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -312,6 +324,9 @@ DnsZonesCNAMERecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -379,7 +394,7 @@ DnsZonesCNAMERecord: Resource └── Type: *string DnsZonesMXRecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -397,6 +412,9 @@ DnsZonesMXRecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -464,7 +482,7 @@ DnsZonesMXRecord: Resource └── Type: *string DnsZonesNSRecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -482,6 +500,9 @@ DnsZonesNSRecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -549,7 +570,7 @@ DnsZonesNSRecord: Resource └── Type: *string DnsZonesPTRRecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -567,6 +588,9 @@ DnsZonesPTRRecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -634,7 +658,7 @@ DnsZonesPTRRecord: Resource └── Type: *string DnsZonesSRVRecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -652,6 +676,9 @@ DnsZonesSRVRecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -719,7 +746,7 @@ DnsZonesSRVRecord: Resource └── Type: *string DnsZonesTXTRecord: Resource ├── Owner: DnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AAAARecords: Object (1 property)[] │ │ └── Ipv6Address: *string │ ├── ARecords: Object (1 property)[] @@ -737,6 +764,9 @@ DnsZonesTXTRecord: Resource │ ├── Metadata: map[string]string │ ├── NSRecords: Object (1 property)[] │ │ └── Nsdname: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PTRRecords: Object (1 property)[] │ │ └── Ptrdname: *string diff --git a/v2/api/network/v1api20180501/zz_generated.deepcopy.go b/v2/api/network/v1api20180501/zz_generated.deepcopy.go index cd9881fa7ac..f05895215ad 100644 --- a/v2/api/network/v1api20180501/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20180501/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180501 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -254,6 +255,43 @@ func (in *DnsZoneList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZoneOperatorSpec) DeepCopyInto(out *DnsZoneOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZoneOperatorSpec. +func (in *DnsZoneOperatorSpec) DeepCopy() *DnsZoneOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZoneOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZone_STATUS) DeepCopyInto(out *DnsZone_STATUS) { *out = *in @@ -355,6 +393,11 @@ func (in *DnsZone_Spec) DeepCopyInto(out *DnsZone_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZoneOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -457,6 +500,43 @@ func (in *DnsZonesAAAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesAAAARecordOperatorSpec) DeepCopyInto(out *DnsZonesAAAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesAAAARecordOperatorSpec. +func (in *DnsZonesAAAARecordOperatorSpec) DeepCopy() *DnsZonesAAAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesAAAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesAAAARecord_STATUS) DeepCopyInto(out *DnsZonesAAAARecord_STATUS) { *out = *in @@ -642,6 +722,11 @@ func (in *DnsZonesAAAARecord_Spec) DeepCopyInto(out *DnsZonesAAAARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesAAAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -754,6 +839,43 @@ func (in *DnsZonesARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesARecordOperatorSpec) DeepCopyInto(out *DnsZonesARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesARecordOperatorSpec. +func (in *DnsZonesARecordOperatorSpec) DeepCopy() *DnsZonesARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesARecord_STATUS) DeepCopyInto(out *DnsZonesARecord_STATUS) { *out = *in @@ -944,6 +1066,11 @@ func (in *DnsZonesARecord_Spec) DeepCopyInto(out *DnsZonesARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1056,6 +1183,43 @@ func (in *DnsZonesCAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesCAARecordOperatorSpec) DeepCopyInto(out *DnsZonesCAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesCAARecordOperatorSpec. +func (in *DnsZonesCAARecordOperatorSpec) DeepCopy() *DnsZonesCAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesCAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesCAARecord_STATUS) DeepCopyInto(out *DnsZonesCAARecord_STATUS) { *out = *in @@ -1241,6 +1405,11 @@ func (in *DnsZonesCAARecord_Spec) DeepCopyInto(out *DnsZonesCAARecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesCAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1353,6 +1522,43 @@ func (in *DnsZonesCNAMERecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesCNAMERecordOperatorSpec) DeepCopyInto(out *DnsZonesCNAMERecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesCNAMERecordOperatorSpec. +func (in *DnsZonesCNAMERecordOperatorSpec) DeepCopy() *DnsZonesCNAMERecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesCNAMERecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesCNAMERecord_STATUS) DeepCopyInto(out *DnsZonesCNAMERecord_STATUS) { *out = *in @@ -1538,6 +1744,11 @@ func (in *DnsZonesCNAMERecord_Spec) DeepCopyInto(out *DnsZonesCNAMERecord_Spec) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesCNAMERecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1650,6 +1861,43 @@ func (in *DnsZonesMXRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesMXRecordOperatorSpec) DeepCopyInto(out *DnsZonesMXRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesMXRecordOperatorSpec. +func (in *DnsZonesMXRecordOperatorSpec) DeepCopy() *DnsZonesMXRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesMXRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesMXRecord_STATUS) DeepCopyInto(out *DnsZonesMXRecord_STATUS) { *out = *in @@ -1835,6 +2083,11 @@ func (in *DnsZonesMXRecord_Spec) DeepCopyInto(out *DnsZonesMXRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesMXRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1947,6 +2200,43 @@ func (in *DnsZonesNSRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesNSRecordOperatorSpec) DeepCopyInto(out *DnsZonesNSRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesNSRecordOperatorSpec. +func (in *DnsZonesNSRecordOperatorSpec) DeepCopy() *DnsZonesNSRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesNSRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesNSRecord_STATUS) DeepCopyInto(out *DnsZonesNSRecord_STATUS) { *out = *in @@ -2132,6 +2422,11 @@ func (in *DnsZonesNSRecord_Spec) DeepCopyInto(out *DnsZonesNSRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesNSRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2244,6 +2539,43 @@ func (in *DnsZonesPTRRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesPTRRecordOperatorSpec) DeepCopyInto(out *DnsZonesPTRRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesPTRRecordOperatorSpec. +func (in *DnsZonesPTRRecordOperatorSpec) DeepCopy() *DnsZonesPTRRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesPTRRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesPTRRecord_STATUS) DeepCopyInto(out *DnsZonesPTRRecord_STATUS) { *out = *in @@ -2429,6 +2761,11 @@ func (in *DnsZonesPTRRecord_Spec) DeepCopyInto(out *DnsZonesPTRRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesPTRRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2541,6 +2878,43 @@ func (in *DnsZonesSRVRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesSRVRecordOperatorSpec) DeepCopyInto(out *DnsZonesSRVRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesSRVRecordOperatorSpec. +func (in *DnsZonesSRVRecordOperatorSpec) DeepCopy() *DnsZonesSRVRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesSRVRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesSRVRecord_STATUS) DeepCopyInto(out *DnsZonesSRVRecord_STATUS) { *out = *in @@ -2726,6 +3100,11 @@ func (in *DnsZonesSRVRecord_Spec) DeepCopyInto(out *DnsZonesSRVRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesSRVRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2838,6 +3217,43 @@ func (in *DnsZonesTXTRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsZonesTXTRecordOperatorSpec) DeepCopyInto(out *DnsZonesTXTRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsZonesTXTRecordOperatorSpec. +func (in *DnsZonesTXTRecordOperatorSpec) DeepCopy() *DnsZonesTXTRecordOperatorSpec { + if in == nil { + return nil + } + out := new(DnsZonesTXTRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsZonesTXTRecord_STATUS) DeepCopyInto(out *DnsZonesTXTRecord_STATUS) { *out = *in @@ -3023,6 +3439,11 @@ func (in *DnsZonesTXTRecord_Spec) DeepCopyInto(out *DnsZonesTXTRecord_Spec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsZonesTXTRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20180901/private_dns_zone_types_gen.go b/v2/api/network/v1api20180901/private_dns_zone_types_gen.go index 3045d5b73fc..4c71b1d44da 100644 --- a/v2/api/network/v1api20180901/private_dns_zone_types_gen.go +++ b/v2/api/network/v1api20180901/private_dns_zone_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (zone *PrivateDnsZone) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZone resource func (zone *PrivateDnsZone) defaultImpl() { zone.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZone{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (zone *PrivateDnsZone) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZone{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (zone *PrivateDnsZone) SecretDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZone{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (zone *PrivateDnsZone) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (zone *PrivateDnsZone) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){zone.validateResourceReferences, zone.validateOwnerReference} + return []func() (admission.Warnings, error){zone.validateResourceReferences, zone.validateOwnerReference, zone.validateSecretDestinations, zone.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (zone *PrivateDnsZone) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return zone.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return zone.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return zone.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (zone *PrivateDnsZone) validateConfigMapDestinations() (admission.Warnings, error) { + if zone.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(zone, nil, zone.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (zone *PrivateDnsZone) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (zone *PrivateDnsZone) validateSecretDestinations() (admission.Warnings, error) { + if zone.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(zone, nil, zone.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (zone *PrivateDnsZone) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZone) @@ -341,6 +386,10 @@ type PrivateDnsZone_Spec struct { // Location: The Azure Region where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZoneOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -412,6 +461,8 @@ func (zone *PrivateDnsZone_Spec) PopulateFromARM(owner genruntime.ArbitraryOwner zone.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": zone.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -492,6 +543,18 @@ func (zone *PrivateDnsZone_Spec) AssignProperties_From_PrivateDnsZone_Spec(sourc // Location zone.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZoneOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZoneOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZoneOperatorSpec() to populate field OperatorSpec") + } + zone.OperatorSpec = &operatorSpec + } else { + zone.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -521,6 +584,18 @@ func (zone *PrivateDnsZone_Spec) AssignProperties_To_PrivateDnsZone_Spec(destina // Location destination.Location = genruntime.ClonePointerToString(zone.Location) + // OperatorSpec + if zone.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZoneOperatorSpec + err := zone.OperatorSpec.AssignProperties_To_PrivateDnsZoneOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZoneOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = zone.OriginalVersion() @@ -914,6 +989,110 @@ func (zone *PrivateDnsZone_STATUS) AssignProperties_To_PrivateDnsZone_STATUS(des return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZoneOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZoneOperatorSpec populates our PrivateDnsZoneOperatorSpec from the provided source PrivateDnsZoneOperatorSpec +func (operator *PrivateDnsZoneOperatorSpec) AssignProperties_From_PrivateDnsZoneOperatorSpec(source *storage.PrivateDnsZoneOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZoneOperatorSpec populates the provided destination PrivateDnsZoneOperatorSpec from our PrivateDnsZoneOperatorSpec +func (operator *PrivateDnsZoneOperatorSpec) AssignProperties_To_PrivateDnsZoneOperatorSpec(destination *storage.PrivateDnsZoneOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type PrivateZoneProperties_ProvisioningState_STATUS string const ( diff --git a/v2/api/network/v1api20180901/private_dns_zone_types_gen_test.go b/v2/api/network/v1api20180901/private_dns_zone_types_gen_test.go index d3a865ce3c3..774678f18ee 100644 --- a/v2/api/network/v1api20180901/private_dns_zone_types_gen_test.go +++ b/v2/api/network/v1api20180901/private_dns_zone_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZone(gens map[string]gopter.Gen) { gens["Status"] = PrivateDnsZone_STATUSGenerator() } +func Test_PrivateDnsZoneOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZoneOperatorSpec to PrivateDnsZoneOperatorSpec via AssignProperties_To_PrivateDnsZoneOperatorSpec & AssignProperties_From_PrivateDnsZoneOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZoneOperatorSpec, PrivateDnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZoneOperatorSpec tests if a specific instance of PrivateDnsZoneOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZoneOperatorSpec(subject PrivateDnsZoneOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZoneOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZoneOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZoneOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZoneOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZoneOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZoneOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZoneOperatorSpec, PrivateDnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZoneOperatorSpec runs a test to see if a specific instance of PrivateDnsZoneOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZoneOperatorSpec(subject PrivateDnsZoneOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZoneOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZoneOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZoneOperatorSpecGenerator() +var privateDnsZoneOperatorSpecGenerator gopter.Gen + +// PrivateDnsZoneOperatorSpecGenerator returns a generator of PrivateDnsZoneOperatorSpec instances for property testing. +func PrivateDnsZoneOperatorSpecGenerator() gopter.Gen { + if privateDnsZoneOperatorSpecGenerator != nil { + return privateDnsZoneOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZoneOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZoneOperatorSpec{}), generators) + + return privateDnsZoneOperatorSpecGenerator +} + func Test_PrivateDnsZone_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -373,6 +470,9 @@ func RunJSONSerializationTestForPrivateDnsZone_Spec(subject PrivateDnsZone_Spec) var privateDnsZone_SpecGenerator gopter.Gen // PrivateDnsZone_SpecGenerator returns a generator of PrivateDnsZone_Spec instances for property testing. +// We first initialize privateDnsZone_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PrivateDnsZone_SpecGenerator() gopter.Gen { if privateDnsZone_SpecGenerator != nil { return privateDnsZone_SpecGenerator @@ -382,6 +482,12 @@ func PrivateDnsZone_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(generators) privateDnsZone_SpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZone_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(generators) + AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec(generators) + privateDnsZone_SpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZone_Spec{}), generators) + return privateDnsZone_SpecGenerator } @@ -394,3 +500,8 @@ func AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(gens map[string]gopt gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZoneOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen.go b/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen.go index d9d867aab34..d8e443809e0 100644 --- a/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen.go +++ b/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (zone *PrivateDnsZone) SetConditions(conditions conditions.Conditions) { zone.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZone{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (zone *PrivateDnsZone) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZone{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (zone *PrivateDnsZone) SecretDestinationExpressions() []*core.DestinationExpression { + if zone.Spec.OperatorSpec == nil { + return nil + } + return zone.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZone{} // AzureName returns the Azure name of the resource @@ -148,10 +171,11 @@ const APIVersion_Value = APIVersion("2018-09-01") type PrivateDnsZone_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Etag *string `json:"etag,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Etag *string `json:"etag,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *PrivateDnsZoneOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -221,6 +245,14 @@ func (zone *PrivateDnsZone_STATUS) ConvertStatusTo(destination genruntime.Conver return destination.ConvertStatusFrom(zone) } +// Storage version of v1api20180901.PrivateDnsZoneOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZoneOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZone{}, &PrivateDnsZoneList{}) } diff --git a/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen_test.go b/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen_test.go index 63784541bec..b3790f8647d 100644 --- a/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen_test.go +++ b/v2/api/network/v1api20180901/storage/private_dns_zone_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZone(gens map[string]gopter.Gen) { gens["Status"] = PrivateDnsZone_STATUSGenerator() } +func Test_PrivateDnsZoneOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZoneOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZoneOperatorSpec, PrivateDnsZoneOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZoneOperatorSpec runs a test to see if a specific instance of PrivateDnsZoneOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZoneOperatorSpec(subject PrivateDnsZoneOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZoneOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZoneOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZoneOperatorSpecGenerator() +var privateDnsZoneOperatorSpecGenerator gopter.Gen + +// PrivateDnsZoneOperatorSpecGenerator returns a generator of PrivateDnsZoneOperatorSpec instances for property testing. +func PrivateDnsZoneOperatorSpecGenerator() gopter.Gen { + if privateDnsZoneOperatorSpecGenerator != nil { + return privateDnsZoneOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZoneOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZoneOperatorSpec{}), generators) + + return privateDnsZoneOperatorSpecGenerator +} + func Test_PrivateDnsZone_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -197,6 +252,9 @@ func RunJSONSerializationTestForPrivateDnsZone_Spec(subject PrivateDnsZone_Spec) var privateDnsZone_SpecGenerator gopter.Gen // PrivateDnsZone_SpecGenerator returns a generator of PrivateDnsZone_Spec instances for property testing. +// We first initialize privateDnsZone_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func PrivateDnsZone_SpecGenerator() gopter.Gen { if privateDnsZone_SpecGenerator != nil { return privateDnsZone_SpecGenerator @@ -206,6 +264,12 @@ func PrivateDnsZone_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(generators) privateDnsZone_SpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZone_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(generators) + AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec(generators) + privateDnsZone_SpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZone_Spec{}), generators) + return privateDnsZone_SpecGenerator } @@ -219,3 +283,8 @@ func AddIndependentPropertyGeneratorsForPrivateDnsZone_Spec(gens map[string]gopt gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForPrivateDnsZone_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZoneOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20180901/storage/structure.txt b/v2/api/network/v1api20180901/storage/structure.txt index 9ffc905f12b..63ae4cfe4f3 100644 --- a/v2/api/network/v1api20180901/storage/structure.txt +++ b/v2/api/network/v1api20180901/storage/structure.txt @@ -5,10 +5,14 @@ APIVersion: Enum (1 value) └── "2018-09-01" PrivateDnsZone: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Etag: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/network/v1api20180901/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20180901/storage/zz_generated.deepcopy.go index b107d8a998b..4e27ed0def5 100644 --- a/v2/api/network/v1api20180901/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20180901/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *PrivateDnsZoneList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZoneOperatorSpec) DeepCopyInto(out *PrivateDnsZoneOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZoneOperatorSpec. +func (in *PrivateDnsZoneOperatorSpec) DeepCopy() *PrivateDnsZoneOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZoneOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZone_STATUS) DeepCopyInto(out *PrivateDnsZone_STATUS) { *out = *in @@ -183,6 +228,11 @@ func (in *PrivateDnsZone_Spec) DeepCopyInto(out *PrivateDnsZone_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZoneOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20180901/structure.txt b/v2/api/network/v1api20180901/structure.txt index 4c582e89a4b..7a82d4a577a 100644 --- a/v2/api/network/v1api20180901/structure.txt +++ b/v2/api/network/v1api20180901/structure.txt @@ -5,10 +5,13 @@ APIVersion: Enum (1 value) └── "2018-09-01" PrivateDnsZone: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Etag: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (14 properties) diff --git a/v2/api/network/v1api20180901/zz_generated.deepcopy.go b/v2/api/network/v1api20180901/zz_generated.deepcopy.go index b99ca0b830d..8e343e046b7 100644 --- a/v2/api/network/v1api20180901/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20180901/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20180901 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,43 @@ func (in *PrivateDnsZoneList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZoneOperatorSpec) DeepCopyInto(out *PrivateDnsZoneOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZoneOperatorSpec. +func (in *PrivateDnsZoneOperatorSpec) DeepCopy() *PrivateDnsZoneOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZoneOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZone_STATUS) DeepCopyInto(out *PrivateDnsZone_STATUS) { *out = *in @@ -176,6 +214,11 @@ func (in *PrivateDnsZone_Spec) DeepCopyInto(out *PrivateDnsZone_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZoneOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen.go index cceceeb4ab2..2f7626bc748 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesARecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesARecord resource func (record *PrivateDnsZonesARecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesARecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesARecord) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (record *PrivateDnsZonesARecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesARecord) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesARecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesARecord) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesARecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesARecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesARecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesARecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesARecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesARecord_Spec) PopulateFromARM(owner genruntime.Arbi } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesARecord_Spec) AssignProperties_From_PrivateDnsZones record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesARecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesARecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesARecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesARecord_Spec) AssignProperties_To_PrivateDnsZonesAR destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesARecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesARecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesARecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesARecord_STATUS) AssignProperties_To_PrivateDnsZones return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesARecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesARecordOperatorSpec populates our PrivateDnsZonesARecordOperatorSpec from the provided source PrivateDnsZonesARecordOperatorSpec +func (operator *PrivateDnsZonesARecordOperatorSpec) AssignProperties_From_PrivateDnsZonesARecordOperatorSpec(source *storage.PrivateDnsZonesARecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesARecordOperatorSpec populates the provided destination PrivateDnsZonesARecordOperatorSpec from our PrivateDnsZonesARecordOperatorSpec +func (operator *PrivateDnsZonesARecordOperatorSpec) AssignProperties_To_PrivateDnsZonesARecordOperatorSpec(destination *storage.PrivateDnsZonesARecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesARecord{}, &PrivateDnsZonesARecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen_test.go index da783459ac0..e8c6827e91e 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_a_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesARecord(gens map[string]gopte gens["Status"] = PrivateDnsZonesARecord_STATUSGenerator() } +func Test_PrivateDnsZonesARecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesARecordOperatorSpec to PrivateDnsZonesARecordOperatorSpec via AssignProperties_To_PrivateDnsZonesARecordOperatorSpec & AssignProperties_From_PrivateDnsZonesARecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesARecordOperatorSpec, PrivateDnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesARecordOperatorSpec tests if a specific instance of PrivateDnsZonesARecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesARecordOperatorSpec(subject PrivateDnsZonesARecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesARecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesARecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec, PrivateDnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec(subject PrivateDnsZonesARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesARecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesARecordOperatorSpecGenerator() +var privateDnsZonesARecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesARecordOperatorSpecGenerator returns a generator of PrivateDnsZonesARecordOperatorSpec instances for property testing. +func PrivateDnsZonesARecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesARecordOperatorSpecGenerator != nil { + return privateDnsZonesARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesARecordOperatorSpec{}), generators) + + return privateDnsZonesARecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesARecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesARecord_Spec(gens map[string] gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesARecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen.go index 6b73f820c1e..62953a0c639 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesAAAARecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesAAAARecord resource func (record *PrivateDnsZonesAAAARecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesAAAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesAAAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesAAAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesAAAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesAAAARecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesAAAARecord) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (record *PrivateDnsZonesAAAARecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesAAAARecord) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesAAAARecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesAAAARecord) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesAAAARecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesAAAARecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesAAAARecord) @@ -353,6 +398,10 @@ type PrivateDnsZonesAAAARecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesAAAARecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -562,6 +611,8 @@ func (record *PrivateDnsZonesAAAARecord_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -762,6 +813,18 @@ func (record *PrivateDnsZonesAAAARecord_Spec) AssignProperties_From_PrivateDnsZo record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesAAAARecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -923,6 +986,18 @@ func (record *PrivateDnsZonesAAAARecord_Spec) AssignProperties_To_PrivateDnsZone destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesAAAARecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -2426,6 +2501,110 @@ func (record *MxRecord_STATUS) AssignProperties_To_MxRecord_STATUS(destination * return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesAAAARecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec populates our PrivateDnsZonesAAAARecordOperatorSpec from the provided source PrivateDnsZonesAAAARecordOperatorSpec +func (operator *PrivateDnsZonesAAAARecordOperatorSpec) AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec(source *storage.PrivateDnsZonesAAAARecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec populates the provided destination PrivateDnsZonesAAAARecordOperatorSpec from our PrivateDnsZonesAAAARecordOperatorSpec +func (operator *PrivateDnsZonesAAAARecordOperatorSpec) AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec(destination *storage.PrivateDnsZonesAAAARecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // A PTR record. type PtrRecord struct { // Ptrdname: The PTR target domain name for this PTR record. diff --git a/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen_test.go index 83703bfcabf..a2a6e864b4e 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_aaaa_record_types_gen_test.go @@ -983,6 +983,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesAAAARecord(gens map[string]go gens["Status"] = PrivateDnsZonesAAAARecord_STATUSGenerator() } +func Test_PrivateDnsZonesAAAARecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesAAAARecordOperatorSpec to PrivateDnsZonesAAAARecordOperatorSpec via AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec & AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesAAAARecordOperatorSpec, PrivateDnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesAAAARecordOperatorSpec tests if a specific instance of PrivateDnsZonesAAAARecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesAAAARecordOperatorSpec(subject PrivateDnsZonesAAAARecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesAAAARecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesAAAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesAAAARecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesAAAARecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesAAAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesAAAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec, PrivateDnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesAAAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec(subject PrivateDnsZonesAAAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesAAAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesAAAARecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesAAAARecordOperatorSpecGenerator() +var privateDnsZonesAAAARecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesAAAARecordOperatorSpecGenerator returns a generator of PrivateDnsZonesAAAARecordOperatorSpec instances for property testing. +func PrivateDnsZonesAAAARecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesAAAARecordOperatorSpecGenerator != nil { + return privateDnsZonesAAAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesAAAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesAAAARecordOperatorSpec{}), generators) + + return privateDnsZonesAAAARecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesAAAARecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1239,6 +1336,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesAAAARecord_Spec(gens map[stri gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesAAAARecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen.go index c60810fc89b..34b293eb611 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesCNAMERecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesCNAMERecord resource func (record *PrivateDnsZonesCNAMERecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesCNAMERecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesCNAMERecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesCNAMERecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesCNAMERecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesCNAMERecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesCNAMERecord) ValidateUpdate(old runtime.Object) (ad // createValidations validates the creation of the resource func (record *PrivateDnsZonesCNAMERecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesCNAMERecord) updateValidations() []func(old runtime func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesCNAMERecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesCNAMERecord) validateResourceReferences() (admissio return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesCNAMERecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesCNAMERecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesCNAMERecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesCNAMERecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesCNAMERecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesCNAMERecord_Spec) PopulateFromARM(owner genruntime. } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesCNAMERecord_Spec) AssignProperties_From_PrivateDnsZ record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesCNAMERecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesCNAMERecord_Spec) AssignProperties_To_PrivateDnsZon destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesCNAMERecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesCNAMERecord_STATUS) AssignProperties_To_PrivateDnsZ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesCNAMERecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec populates our PrivateDnsZonesCNAMERecordOperatorSpec from the provided source PrivateDnsZonesCNAMERecordOperatorSpec +func (operator *PrivateDnsZonesCNAMERecordOperatorSpec) AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec(source *storage.PrivateDnsZonesCNAMERecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec populates the provided destination PrivateDnsZonesCNAMERecordOperatorSpec from our PrivateDnsZonesCNAMERecordOperatorSpec +func (operator *PrivateDnsZonesCNAMERecordOperatorSpec) AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec(destination *storage.PrivateDnsZonesCNAMERecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesCNAMERecord{}, &PrivateDnsZonesCNAMERecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen_test.go index 5e1e69bb115..d79fce34ee2 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_cname_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesCNAMERecord(gens map[string]g gens["Status"] = PrivateDnsZonesCNAMERecord_STATUSGenerator() } +func Test_PrivateDnsZonesCNAMERecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesCNAMERecordOperatorSpec to PrivateDnsZonesCNAMERecordOperatorSpec via AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec & AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesCNAMERecordOperatorSpec, PrivateDnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesCNAMERecordOperatorSpec tests if a specific instance of PrivateDnsZonesCNAMERecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesCNAMERecordOperatorSpec(subject PrivateDnsZonesCNAMERecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesCNAMERecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesCNAMERecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesCNAMERecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesCNAMERecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesCNAMERecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesCNAMERecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec, PrivateDnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesCNAMERecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec(subject PrivateDnsZonesCNAMERecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesCNAMERecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesCNAMERecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesCNAMERecordOperatorSpecGenerator() +var privateDnsZonesCNAMERecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesCNAMERecordOperatorSpecGenerator returns a generator of PrivateDnsZonesCNAMERecordOperatorSpec instances for property testing. +func PrivateDnsZonesCNAMERecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesCNAMERecordOperatorSpecGenerator != nil { + return privateDnsZonesCNAMERecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesCNAMERecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesCNAMERecordOperatorSpec{}), generators) + + return privateDnsZonesCNAMERecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesCNAMERecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesCNAMERecord_Spec(gens map[str gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesCNAMERecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen.go index c2f9f89306c..2be4702c1e7 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesMXRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesMXRecord resource func (record *PrivateDnsZonesMXRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesMXRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesMXRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesMXRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesMXRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesMXRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesMXRecord) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (record *PrivateDnsZonesMXRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesMXRecord) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesMXRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesMXRecord) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesMXRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesMXRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesMXRecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesMXRecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesMXRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesMXRecord_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesMXRecord_Spec) AssignProperties_From_PrivateDnsZone record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesMXRecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesMXRecord_Spec) AssignProperties_To_PrivateDnsZonesM destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesMXRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesMXRecord_STATUS) AssignProperties_To_PrivateDnsZone return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesMXRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec populates our PrivateDnsZonesMXRecordOperatorSpec from the provided source PrivateDnsZonesMXRecordOperatorSpec +func (operator *PrivateDnsZonesMXRecordOperatorSpec) AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec(source *storage.PrivateDnsZonesMXRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec populates the provided destination PrivateDnsZonesMXRecordOperatorSpec from our PrivateDnsZonesMXRecordOperatorSpec +func (operator *PrivateDnsZonesMXRecordOperatorSpec) AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec(destination *storage.PrivateDnsZonesMXRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesMXRecord{}, &PrivateDnsZonesMXRecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen_test.go index 1e0c97720c0..f891fcfdeb2 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_mx_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesMXRecord(gens map[string]gopt gens["Status"] = PrivateDnsZonesMXRecord_STATUSGenerator() } +func Test_PrivateDnsZonesMXRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesMXRecordOperatorSpec to PrivateDnsZonesMXRecordOperatorSpec via AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec & AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesMXRecordOperatorSpec, PrivateDnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesMXRecordOperatorSpec tests if a specific instance of PrivateDnsZonesMXRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesMXRecordOperatorSpec(subject PrivateDnsZonesMXRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesMXRecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesMXRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesMXRecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesMXRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesMXRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesMXRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec, PrivateDnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesMXRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec(subject PrivateDnsZonesMXRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesMXRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesMXRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesMXRecordOperatorSpecGenerator() +var privateDnsZonesMXRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesMXRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesMXRecordOperatorSpec instances for property testing. +func PrivateDnsZonesMXRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesMXRecordOperatorSpecGenerator != nil { + return privateDnsZonesMXRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesMXRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesMXRecordOperatorSpec{}), generators) + + return privateDnsZonesMXRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesMXRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesMXRecord_Spec(gens map[string gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesMXRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen.go index 449216bb56e..b73edb6c36e 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesPTRRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesPTRRecord resource func (record *PrivateDnsZonesPTRRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesPTRRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesPTRRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesPTRRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesPTRRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesPTRRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesPTRRecord) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (record *PrivateDnsZonesPTRRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesPTRRecord) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesPTRRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesPTRRecord) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesPTRRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesPTRRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesPTRRecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesPTRRecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesPTRRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesPTRRecord_Spec) PopulateFromARM(owner genruntime.Ar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesPTRRecord_Spec) AssignProperties_From_PrivateDnsZon record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesPTRRecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesPTRRecord_Spec) AssignProperties_To_PrivateDnsZones destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesPTRRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesPTRRecord_STATUS) AssignProperties_To_PrivateDnsZon return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesPTRRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec populates our PrivateDnsZonesPTRRecordOperatorSpec from the provided source PrivateDnsZonesPTRRecordOperatorSpec +func (operator *PrivateDnsZonesPTRRecordOperatorSpec) AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec(source *storage.PrivateDnsZonesPTRRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec populates the provided destination PrivateDnsZonesPTRRecordOperatorSpec from our PrivateDnsZonesPTRRecordOperatorSpec +func (operator *PrivateDnsZonesPTRRecordOperatorSpec) AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec(destination *storage.PrivateDnsZonesPTRRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesPTRRecord{}, &PrivateDnsZonesPTRRecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen_test.go index 140b2a2e78c..4f889511c53 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_ptr_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesPTRRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesPTRRecord_STATUSGenerator() } +func Test_PrivateDnsZonesPTRRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesPTRRecordOperatorSpec to PrivateDnsZonesPTRRecordOperatorSpec via AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec & AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesPTRRecordOperatorSpec, PrivateDnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesPTRRecordOperatorSpec tests if a specific instance of PrivateDnsZonesPTRRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesPTRRecordOperatorSpec(subject PrivateDnsZonesPTRRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesPTRRecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesPTRRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesPTRRecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesPTRRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesPTRRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesPTRRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec, PrivateDnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesPTRRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec(subject PrivateDnsZonesPTRRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesPTRRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesPTRRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesPTRRecordOperatorSpecGenerator() +var privateDnsZonesPTRRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesPTRRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesPTRRecordOperatorSpec instances for property testing. +func PrivateDnsZonesPTRRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesPTRRecordOperatorSpecGenerator != nil { + return privateDnsZonesPTRRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesPTRRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesPTRRecordOperatorSpec{}), generators) + + return privateDnsZonesPTRRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesPTRRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesPTRRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesPTRRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen.go index 4ac2e71a3e9..45b376d7ba2 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesSRVRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesSRVRecord resource func (record *PrivateDnsZonesSRVRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesSRVRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesSRVRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesSRVRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesSRVRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesSRVRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesSRVRecord) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (record *PrivateDnsZonesSRVRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesSRVRecord) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesSRVRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesSRVRecord) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesSRVRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesSRVRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesSRVRecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesSRVRecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesSRVRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesSRVRecord_Spec) PopulateFromARM(owner genruntime.Ar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesSRVRecord_Spec) AssignProperties_From_PrivateDnsZon record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesSRVRecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesSRVRecord_Spec) AssignProperties_To_PrivateDnsZones destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesSRVRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesSRVRecord_STATUS) AssignProperties_To_PrivateDnsZon return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesSRVRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec populates our PrivateDnsZonesSRVRecordOperatorSpec from the provided source PrivateDnsZonesSRVRecordOperatorSpec +func (operator *PrivateDnsZonesSRVRecordOperatorSpec) AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec(source *storage.PrivateDnsZonesSRVRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec populates the provided destination PrivateDnsZonesSRVRecordOperatorSpec from our PrivateDnsZonesSRVRecordOperatorSpec +func (operator *PrivateDnsZonesSRVRecordOperatorSpec) AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec(destination *storage.PrivateDnsZonesSRVRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesSRVRecord{}, &PrivateDnsZonesSRVRecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen_test.go index 687e583c7bc..264c09125cb 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_srv_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesSRVRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesSRVRecord_STATUSGenerator() } +func Test_PrivateDnsZonesSRVRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesSRVRecordOperatorSpec to PrivateDnsZonesSRVRecordOperatorSpec via AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec & AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesSRVRecordOperatorSpec, PrivateDnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesSRVRecordOperatorSpec tests if a specific instance of PrivateDnsZonesSRVRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesSRVRecordOperatorSpec(subject PrivateDnsZonesSRVRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesSRVRecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesSRVRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesSRVRecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesSRVRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesSRVRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesSRVRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec, PrivateDnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesSRVRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec(subject PrivateDnsZonesSRVRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesSRVRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesSRVRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesSRVRecordOperatorSpecGenerator() +var privateDnsZonesSRVRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesSRVRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesSRVRecordOperatorSpec instances for property testing. +func PrivateDnsZonesSRVRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesSRVRecordOperatorSpecGenerator != nil { + return privateDnsZonesSRVRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesSRVRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesSRVRecordOperatorSpec{}), generators) + + return privateDnsZonesSRVRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesSRVRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesSRVRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesSRVRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen.go index 2f542dff588..9e55e21f0e6 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (record *PrivateDnsZonesTXTRecord) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesTXTRecord resource func (record *PrivateDnsZonesTXTRecord) defaultImpl() { record.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesTXTRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesTXTRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesTXTRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesTXTRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesTXTRecord{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (record *PrivateDnsZonesTXTRecord) ValidateUpdate(old runtime.Object) (admi // createValidations validates the creation of the resource func (record *PrivateDnsZonesTXTRecord) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference} + return []func() (admission.Warnings, error){record.validateResourceReferences, record.validateOwnerReference, record.validateSecretDestinations, record.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (record *PrivateDnsZonesTXTRecord) updateValidations() []func(old runtime.O func(old runtime.Object) (admission.Warnings, error) { return record.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return record.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (record *PrivateDnsZonesTXTRecord) validateConfigMapDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(record, nil, record.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (record *PrivateDnsZonesTXTRecord) validateResourceReferences() (admission. return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (record *PrivateDnsZonesTXTRecord) validateSecretDestinations() (admission.Warnings, error) { + if record.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(record, nil, record.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (record *PrivateDnsZonesTXTRecord) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesTXTRecord) @@ -348,6 +393,10 @@ type PrivateDnsZonesTXTRecord_Spec struct { // MxRecords: The list of MX records in the record set. MxRecords []MxRecord `json:"mxRecords,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesTXTRecordOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -557,6 +606,8 @@ func (record *PrivateDnsZonesTXTRecord_Spec) PopulateFromARM(owner genruntime.Ar } } + // no assignment for property "OperatorSpec" + // Set property "Owner": record.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -757,6 +808,18 @@ func (record *PrivateDnsZonesTXTRecord_Spec) AssignProperties_From_PrivateDnsZon record.MxRecords = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesTXTRecordOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec() to populate field OperatorSpec") + } + record.OperatorSpec = &operatorSpec + } else { + record.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -918,6 +981,18 @@ func (record *PrivateDnsZonesTXTRecord_Spec) AssignProperties_To_PrivateDnsZones destination.MxRecords = nil } + // OperatorSpec + if record.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesTXTRecordOperatorSpec + err := record.OperatorSpec.AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = record.OriginalVersion() @@ -1810,6 +1885,110 @@ func (record *PrivateDnsZonesTXTRecord_STATUS) AssignProperties_To_PrivateDnsZon return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesTXTRecordOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec populates our PrivateDnsZonesTXTRecordOperatorSpec from the provided source PrivateDnsZonesTXTRecordOperatorSpec +func (operator *PrivateDnsZonesTXTRecordOperatorSpec) AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec(source *storage.PrivateDnsZonesTXTRecordOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec populates the provided destination PrivateDnsZonesTXTRecordOperatorSpec from our PrivateDnsZonesTXTRecordOperatorSpec +func (operator *PrivateDnsZonesTXTRecordOperatorSpec) AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec(destination *storage.PrivateDnsZonesTXTRecordOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesTXTRecord{}, &PrivateDnsZonesTXTRecordList{}) } diff --git a/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen_test.go index cc0d9380831..e752aa9d4fc 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_txt_record_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesTXTRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesTXTRecord_STATUSGenerator() } +func Test_PrivateDnsZonesTXTRecordOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesTXTRecordOperatorSpec to PrivateDnsZonesTXTRecordOperatorSpec via AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec & AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesTXTRecordOperatorSpec, PrivateDnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesTXTRecordOperatorSpec tests if a specific instance of PrivateDnsZonesTXTRecordOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesTXTRecordOperatorSpec(subject PrivateDnsZonesTXTRecordOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesTXTRecordOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesTXTRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesTXTRecordOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesTXTRecordOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesTXTRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesTXTRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec, PrivateDnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesTXTRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec(subject PrivateDnsZonesTXTRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesTXTRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesTXTRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesTXTRecordOperatorSpecGenerator() +var privateDnsZonesTXTRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesTXTRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesTXTRecordOperatorSpec instances for property testing. +func PrivateDnsZonesTXTRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesTXTRecordOperatorSpecGenerator != nil { + return privateDnsZonesTXTRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesTXTRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesTXTRecordOperatorSpec{}), generators) + + return privateDnsZonesTXTRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesTXTRecord_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -421,6 +518,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesTXTRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesTXTRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen.go b/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen.go index 1ba284f63c3..28970135d19 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen.go +++ b/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (link *PrivateDnsZonesVirtualNetworkLink) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateDnsZonesVirtualNetworkLink resource func (link *PrivateDnsZonesVirtualNetworkLink) defaultImpl() { link.defaultAzureName() } +var _ configmaps.Exporter = &PrivateDnsZonesVirtualNetworkLink{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (link *PrivateDnsZonesVirtualNetworkLink) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesVirtualNetworkLink{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (link *PrivateDnsZonesVirtualNetworkLink) SecretDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateDnsZonesVirtualNetworkLink{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (link *PrivateDnsZonesVirtualNetworkLink) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (link *PrivateDnsZonesVirtualNetworkLink) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){link.validateResourceReferences, link.validateOwnerReference} + return []func() (admission.Warnings, error){link.validateResourceReferences, link.validateOwnerReference, link.validateSecretDestinations, link.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (link *PrivateDnsZonesVirtualNetworkLink) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return link.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return link.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return link.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (link *PrivateDnsZonesVirtualNetworkLink) validateConfigMapDestinations() (admission.Warnings, error) { + if link.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(link, nil, link.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (link *PrivateDnsZonesVirtualNetworkLink) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (link *PrivateDnsZonesVirtualNetworkLink) validateSecretDestinations() (admission.Warnings, error) { + if link.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(link, nil, link.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (link *PrivateDnsZonesVirtualNetworkLink) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateDnsZonesVirtualNetworkLink) @@ -336,6 +381,10 @@ type PrivateDnsZonesVirtualNetworkLink_Spec struct { // Location: The Azure Region where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateDnsZonesVirtualNetworkLinkOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -431,6 +480,8 @@ func (link *PrivateDnsZonesVirtualNetworkLink_Spec) PopulateFromARM(owner genrun link.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": link.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -534,6 +585,18 @@ func (link *PrivateDnsZonesVirtualNetworkLink_Spec) AssignProperties_From_Privat // Location link.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec() to populate field OperatorSpec") + } + link.OperatorSpec = &operatorSpec + } else { + link.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -583,6 +646,18 @@ func (link *PrivateDnsZonesVirtualNetworkLink_Spec) AssignProperties_To_PrivateD // Location destination.Location = genruntime.ClonePointerToString(link.Location) + // OperatorSpec + if link.OperatorSpec != nil { + var operatorSpec storage.PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err := link.OperatorSpec.AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = link.OriginalVersion() @@ -1005,6 +1080,110 @@ func (link *PrivateDnsZonesVirtualNetworkLink_STATUS) AssignProperties_To_Privat return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesVirtualNetworkLinkOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec populates our PrivateDnsZonesVirtualNetworkLinkOperatorSpec from the provided source PrivateDnsZonesVirtualNetworkLinkOperatorSpec +func (operator *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(source *storage.PrivateDnsZonesVirtualNetworkLinkOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec populates the provided destination PrivateDnsZonesVirtualNetworkLinkOperatorSpec from our PrivateDnsZonesVirtualNetworkLinkOperatorSpec +func (operator *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(destination *storage.PrivateDnsZonesVirtualNetworkLinkOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Reference to another subresource. type SubResource struct { // Reference: Resource ID. diff --git a/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen_test.go b/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen_test.go index b7de19d343b..36be2ca4ae0 100644 --- a/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen_test.go +++ b/v2/api/network/v1api20200601/private_dns_zones_virtual_network_link_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink(gens map[s gens["Status"] = PrivateDnsZonesVirtualNetworkLink_STATUSGenerator() } +func Test_PrivateDnsZonesVirtualNetworkLinkOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateDnsZonesVirtualNetworkLinkOperatorSpec to PrivateDnsZonesVirtualNetworkLinkOperatorSpec via AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec & AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec, PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec tests if a specific instance of PrivateDnsZonesVirtualNetworkLinkOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec(subject PrivateDnsZonesVirtualNetworkLinkOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err := copied.AssignProperties_To_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err = actual.AssignProperties_From_PrivateDnsZonesVirtualNetworkLinkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateDnsZonesVirtualNetworkLinkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesVirtualNetworkLinkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec, PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesVirtualNetworkLinkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec(subject PrivateDnsZonesVirtualNetworkLinkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesVirtualNetworkLinkOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator() +var privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator returns a generator of PrivateDnsZonesVirtualNetworkLinkOperatorSpec instances for property testing. +func PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator != nil { + return privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesVirtualNetworkLinkOperatorSpec{}), generators) + + return privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator +} + func Test_PrivateDnsZonesVirtualNetworkLink_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -418,6 +515,7 @@ func AddIndependentPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec(g // AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(SubResourceGenerator()) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen.go index e775d125272..69c384e74c6 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesARecord) SetConditions(conditions conditions.Condit record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesARecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesARecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesARecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesARecord_STATUS) ConvertStatusTo(destination genrunt return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesARecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesARecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesARecord{}, &PrivateDnsZonesARecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen_test.go index 79ae37f431a..694466e06a1 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_a_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesARecord(gens map[string]gopte gens["Status"] = PrivateDnsZonesARecord_STATUSGenerator() } +func Test_PrivateDnsZonesARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec, PrivateDnsZonesARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesARecordOperatorSpec(subject PrivateDnsZonesARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesARecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesARecordOperatorSpecGenerator() +var privateDnsZonesARecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesARecordOperatorSpecGenerator returns a generator of PrivateDnsZonesARecordOperatorSpec instances for property testing. +func PrivateDnsZonesARecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesARecordOperatorSpecGenerator != nil { + return privateDnsZonesARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesARecordOperatorSpec{}), generators) + + return privateDnsZonesARecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesARecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesARecord_Spec(gens map[string] gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesARecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen.go index b15ddaf887d..67d0d0e45fe 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesAAAARecord) SetConditions(conditions conditions.Con record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesAAAARecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesAAAARecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesAAAARecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesAAAARecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesAAAARecord{} // AzureName returns the Azure name of the resource @@ -151,12 +174,13 @@ type PrivateDnsZonesAAAARecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesAAAARecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -291,6 +315,14 @@ type MxRecord_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20200601.PrivateDnsZonesAAAARecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesAAAARecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20200601.PtrRecord // A PTR record. type PtrRecord struct { diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen_test.go index ab1f33203d8..07926280524 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_aaaa_record_types_gen_test.go @@ -561,6 +561,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesAAAARecord(gens map[string]go gens["Status"] = PrivateDnsZonesAAAARecord_STATUSGenerator() } +func Test_PrivateDnsZonesAAAARecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesAAAARecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec, PrivateDnsZonesAAAARecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesAAAARecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesAAAARecordOperatorSpec(subject PrivateDnsZonesAAAARecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesAAAARecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesAAAARecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesAAAARecordOperatorSpecGenerator() +var privateDnsZonesAAAARecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesAAAARecordOperatorSpecGenerator returns a generator of PrivateDnsZonesAAAARecordOperatorSpec instances for property testing. +func PrivateDnsZonesAAAARecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesAAAARecordOperatorSpecGenerator != nil { + return privateDnsZonesAAAARecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesAAAARecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesAAAARecordOperatorSpec{}), generators) + + return privateDnsZonesAAAARecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesAAAARecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -734,6 +789,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesAAAARecord_Spec(gens map[stri gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesAAAARecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen.go index 05fc9c7954f..583eeccf28b 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesCNAMERecord) SetConditions(conditions conditions.Co record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesCNAMERecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesCNAMERecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesCNAMERecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesCNAMERecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesCNAMERecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesCNAMERecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesCNAMERecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesCNAMERecord_STATUS) ConvertStatusTo(destination gen return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesCNAMERecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesCNAMERecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesCNAMERecord{}, &PrivateDnsZonesCNAMERecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen_test.go index ac0d2671cb0..833ec5f6393 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_cname_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesCNAMERecord(gens map[string]g gens["Status"] = PrivateDnsZonesCNAMERecord_STATUSGenerator() } +func Test_PrivateDnsZonesCNAMERecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesCNAMERecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec, PrivateDnsZonesCNAMERecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesCNAMERecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesCNAMERecordOperatorSpec(subject PrivateDnsZonesCNAMERecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesCNAMERecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesCNAMERecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesCNAMERecordOperatorSpecGenerator() +var privateDnsZonesCNAMERecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesCNAMERecordOperatorSpecGenerator returns a generator of PrivateDnsZonesCNAMERecordOperatorSpec instances for property testing. +func PrivateDnsZonesCNAMERecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesCNAMERecordOperatorSpecGenerator != nil { + return privateDnsZonesCNAMERecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesCNAMERecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesCNAMERecordOperatorSpec{}), generators) + + return privateDnsZonesCNAMERecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesCNAMERecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesCNAMERecord_Spec(gens map[str gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesCNAMERecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen.go index d023987e939..589e46e5ad1 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesMXRecord) SetConditions(conditions conditions.Condi record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesMXRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesMXRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesMXRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesMXRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesMXRecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesMXRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesMXRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesMXRecord_STATUS) ConvertStatusTo(destination genrun return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesMXRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesMXRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesMXRecord{}, &PrivateDnsZonesMXRecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen_test.go index a7dcce9667e..d491ddb1b96 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_mx_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesMXRecord(gens map[string]gopt gens["Status"] = PrivateDnsZonesMXRecord_STATUSGenerator() } +func Test_PrivateDnsZonesMXRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesMXRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec, PrivateDnsZonesMXRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesMXRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesMXRecordOperatorSpec(subject PrivateDnsZonesMXRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesMXRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesMXRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesMXRecordOperatorSpecGenerator() +var privateDnsZonesMXRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesMXRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesMXRecordOperatorSpec instances for property testing. +func PrivateDnsZonesMXRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesMXRecordOperatorSpecGenerator != nil { + return privateDnsZonesMXRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesMXRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesMXRecordOperatorSpec{}), generators) + + return privateDnsZonesMXRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesMXRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesMXRecord_Spec(gens map[string gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesMXRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen.go index 44b4fe8647c..cf2104f1bb2 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesPTRRecord) SetConditions(conditions conditions.Cond record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesPTRRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesPTRRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesPTRRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesPTRRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesPTRRecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesPTRRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesPTRRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesPTRRecord_STATUS) ConvertStatusTo(destination genru return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesPTRRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesPTRRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesPTRRecord{}, &PrivateDnsZonesPTRRecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen_test.go index 71b37c2c6ab..ebc5dd0e814 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_ptr_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesPTRRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesPTRRecord_STATUSGenerator() } +func Test_PrivateDnsZonesPTRRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesPTRRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec, PrivateDnsZonesPTRRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesPTRRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesPTRRecordOperatorSpec(subject PrivateDnsZonesPTRRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesPTRRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesPTRRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesPTRRecordOperatorSpecGenerator() +var privateDnsZonesPTRRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesPTRRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesPTRRecordOperatorSpec instances for property testing. +func PrivateDnsZonesPTRRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesPTRRecordOperatorSpecGenerator != nil { + return privateDnsZonesPTRRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesPTRRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesPTRRecordOperatorSpec{}), generators) + + return privateDnsZonesPTRRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesPTRRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesPTRRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesPTRRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen.go index ade7277e250..cef77a790dd 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesSRVRecord) SetConditions(conditions conditions.Cond record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesSRVRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesSRVRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesSRVRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesSRVRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesSRVRecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesSRVRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesSRVRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesSRVRecord_STATUS) ConvertStatusTo(destination genru return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesSRVRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesSRVRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesSRVRecord{}, &PrivateDnsZonesSRVRecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen_test.go index 5b7d3ebab19..d8b7cfaa7d1 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_srv_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesSRVRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesSRVRecord_STATUSGenerator() } +func Test_PrivateDnsZonesSRVRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesSRVRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec, PrivateDnsZonesSRVRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesSRVRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesSRVRecordOperatorSpec(subject PrivateDnsZonesSRVRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesSRVRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesSRVRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesSRVRecordOperatorSpecGenerator() +var privateDnsZonesSRVRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesSRVRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesSRVRecordOperatorSpec instances for property testing. +func PrivateDnsZonesSRVRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesSRVRecordOperatorSpecGenerator != nil { + return privateDnsZonesSRVRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesSRVRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesSRVRecordOperatorSpec{}), generators) + + return privateDnsZonesSRVRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesSRVRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesSRVRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesSRVRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen.go index fb84587a50d..c3578f608fc 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (record *PrivateDnsZonesTXTRecord) SetConditions(conditions conditions.Cond record.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesTXTRecord{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (record *PrivateDnsZonesTXTRecord) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesTXTRecord{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (record *PrivateDnsZonesTXTRecord) SecretDestinationExpressions() []*core.DestinationExpression { + if record.Spec.OperatorSpec == nil { + return nil + } + return record.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesTXTRecord{} // AzureName returns the Azure name of the resource @@ -145,12 +168,13 @@ type PrivateDnsZonesTXTRecord_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` - Etag *string `json:"etag,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - MxRecords []MxRecord `json:"mxRecords,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CnameRecord *CnameRecord `json:"cnameRecord,omitempty"` + Etag *string `json:"etag,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + MxRecords []MxRecord `json:"mxRecords,omitempty"` + OperatorSpec *PrivateDnsZonesTXTRecordOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -227,6 +251,14 @@ func (record *PrivateDnsZonesTXTRecord_STATUS) ConvertStatusTo(destination genru return destination.ConvertStatusFrom(record) } +// Storage version of v1api20200601.PrivateDnsZonesTXTRecordOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesTXTRecordOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&PrivateDnsZonesTXTRecord{}, &PrivateDnsZonesTXTRecordList{}) } diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen_test.go index 3b864ba4928..cfb800520b3 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_txt_record_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesTXTRecord(gens map[string]gop gens["Status"] = PrivateDnsZonesTXTRecord_STATUSGenerator() } +func Test_PrivateDnsZonesTXTRecordOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesTXTRecordOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec, PrivateDnsZonesTXTRecordOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesTXTRecordOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesTXTRecordOperatorSpec(subject PrivateDnsZonesTXTRecordOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesTXTRecordOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesTXTRecordOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesTXTRecordOperatorSpecGenerator() +var privateDnsZonesTXTRecordOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesTXTRecordOperatorSpecGenerator returns a generator of PrivateDnsZonesTXTRecordOperatorSpec instances for property testing. +func PrivateDnsZonesTXTRecordOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesTXTRecordOperatorSpecGenerator != nil { + return privateDnsZonesTXTRecordOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesTXTRecordOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesTXTRecordOperatorSpec{}), generators) + + return privateDnsZonesTXTRecordOperatorSpecGenerator +} + func Test_PrivateDnsZonesTXTRecord_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -252,6 +307,7 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesTXTRecord_Spec(gens map[strin gens["AaaaRecords"] = gen.SliceOf(AaaaRecordGenerator()) gens["CnameRecord"] = gen.PtrOf(CnameRecordGenerator()) gens["MxRecords"] = gen.SliceOf(MxRecordGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesTXTRecordOperatorSpecGenerator()) gens["PtrRecords"] = gen.SliceOf(PtrRecordGenerator()) gens["SoaRecord"] = gen.PtrOf(SoaRecordGenerator()) gens["SrvRecords"] = gen.SliceOf(SrvRecordGenerator()) diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen.go b/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen.go index 27ce91fe5e6..a92a2f75cf5 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20201101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (link *PrivateDnsZonesVirtualNetworkLink) SetConditions(conditions conditio link.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateDnsZonesVirtualNetworkLink{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (link *PrivateDnsZonesVirtualNetworkLink) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateDnsZonesVirtualNetworkLink{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (link *PrivateDnsZonesVirtualNetworkLink) SecretDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateDnsZonesVirtualNetworkLink{} // AzureName returns the Azure name of the resource @@ -143,10 +166,11 @@ type PrivateDnsZonesVirtualNetworkLinkList struct { type PrivateDnsZonesVirtualNetworkLink_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Etag *string `json:"etag,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Etag *string `json:"etag,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *PrivateDnsZonesVirtualNetworkLinkOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -215,6 +239,14 @@ func (link *PrivateDnsZonesVirtualNetworkLink_STATUS) ConvertStatusTo(destinatio return destination.ConvertStatusFrom(link) } +// Storage version of v1api20200601.PrivateDnsZonesVirtualNetworkLinkOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateDnsZonesVirtualNetworkLinkOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20200601.SubResource // Reference to another subresource. type SubResource struct { diff --git a/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen_test.go b/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen_test.go index b7f2fa3199d..8a896ef8491 100644 --- a/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen_test.go +++ b/v2/api/network/v1api20200601/storage/private_dns_zones_virtual_network_link_types_gen_test.go @@ -80,6 +80,61 @@ func AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink(gens map[s gens["Status"] = PrivateDnsZonesVirtualNetworkLink_STATUSGenerator() } +func Test_PrivateDnsZonesVirtualNetworkLinkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateDnsZonesVirtualNetworkLinkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec, PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec runs a test to see if a specific instance of PrivateDnsZonesVirtualNetworkLinkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateDnsZonesVirtualNetworkLinkOperatorSpec(subject PrivateDnsZonesVirtualNetworkLinkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateDnsZonesVirtualNetworkLinkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateDnsZonesVirtualNetworkLinkOperatorSpec instances for property testing - lazily instantiated by +// PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator() +var privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator gopter.Gen + +// PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator returns a generator of PrivateDnsZonesVirtualNetworkLinkOperatorSpec instances for property testing. +func PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator() gopter.Gen { + if privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator != nil { + return privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateDnsZonesVirtualNetworkLinkOperatorSpec{}), generators) + + return privateDnsZonesVirtualNetworkLinkOperatorSpecGenerator +} + func Test_PrivateDnsZonesVirtualNetworkLink_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -244,6 +299,7 @@ func AddIndependentPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec(g // AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrivateDnsZonesVirtualNetworkLink_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateDnsZonesVirtualNetworkLinkOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(SubResourceGenerator()) } diff --git a/v2/api/network/v1api20200601/storage/structure.txt b/v2/api/network/v1api20200601/storage/structure.txt index e9cb276b64a..3dc08c378ed 100644 --- a/v2/api/network/v1api20200601/storage/structure.txt +++ b/v2/api/network/v1api20200601/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-06-01" PrivateDnsZonesAAAARecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -22,6 +22,10 @@ PrivateDnsZonesAAAARecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -94,7 +98,7 @@ PrivateDnsZonesAAAARecord: Resource └── Type: *string PrivateDnsZonesARecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -111,6 +115,10 @@ PrivateDnsZonesARecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -183,7 +191,7 @@ PrivateDnsZonesARecord: Resource └── Type: *string PrivateDnsZonesCNAMERecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -200,6 +208,10 @@ PrivateDnsZonesCNAMERecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -272,7 +284,7 @@ PrivateDnsZonesCNAMERecord: Resource └── Type: *string PrivateDnsZonesMXRecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -289,6 +301,10 @@ PrivateDnsZonesMXRecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -361,7 +377,7 @@ PrivateDnsZonesMXRecord: Resource └── Type: *string PrivateDnsZonesPTRRecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -378,6 +394,10 @@ PrivateDnsZonesPTRRecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -450,7 +470,7 @@ PrivateDnsZonesPTRRecord: Resource └── Type: *string PrivateDnsZonesSRVRecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -467,6 +487,10 @@ PrivateDnsZonesSRVRecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -539,7 +563,7 @@ PrivateDnsZonesSRVRecord: Resource └── Type: *string PrivateDnsZonesTXTRecord: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── ARecords: Object (2 properties)[] │ │ ├── Ipv4Address: *string │ │ └── PropertyBag: genruntime.PropertyBag @@ -556,6 +580,10 @@ PrivateDnsZonesTXTRecord: Resource │ │ ├── Exchange: *string │ │ ├── Preference: *int │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -628,10 +656,14 @@ PrivateDnsZonesTXTRecord: Resource └── Type: *string PrivateDnsZonesVirtualNetworkLink: Resource ├── Owner: network/v1api20200601.PrivateDnsZone -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── Etag: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/network/v1api20200601/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20200601/storage/zz_generated.deepcopy.go index 7a04b32e67b..557fb5738ee 100644 --- a/v2/api/network/v1api20200601/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20200601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -300,6 +301,50 @@ func (in *PrivateDnsZonesAAAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesAAAARecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesAAAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesAAAARecordOperatorSpec. +func (in *PrivateDnsZonesAAAARecordOperatorSpec) DeepCopy() *PrivateDnsZonesAAAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesAAAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesAAAARecord_STATUS) DeepCopyInto(out *PrivateDnsZonesAAAARecord_STATUS) { *out = *in @@ -464,6 +509,11 @@ func (in *PrivateDnsZonesAAAARecord_Spec) DeepCopyInto(out *PrivateDnsZonesAAAAR (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesAAAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -578,6 +628,50 @@ func (in *PrivateDnsZonesARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesARecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesARecordOperatorSpec. +func (in *PrivateDnsZonesARecordOperatorSpec) DeepCopy() *PrivateDnsZonesARecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesARecord_STATUS) DeepCopyInto(out *PrivateDnsZonesARecord_STATUS) { *out = *in @@ -742,6 +836,11 @@ func (in *PrivateDnsZonesARecord_Spec) DeepCopyInto(out *PrivateDnsZonesARecord_ (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -856,6 +955,50 @@ func (in *PrivateDnsZonesCNAMERecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesCNAMERecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesCNAMERecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesCNAMERecordOperatorSpec. +func (in *PrivateDnsZonesCNAMERecordOperatorSpec) DeepCopy() *PrivateDnsZonesCNAMERecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesCNAMERecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesCNAMERecord_STATUS) DeepCopyInto(out *PrivateDnsZonesCNAMERecord_STATUS) { *out = *in @@ -1020,6 +1163,11 @@ func (in *PrivateDnsZonesCNAMERecord_Spec) DeepCopyInto(out *PrivateDnsZonesCNAM (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesCNAMERecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1134,6 +1282,50 @@ func (in *PrivateDnsZonesMXRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesMXRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesMXRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesMXRecordOperatorSpec. +func (in *PrivateDnsZonesMXRecordOperatorSpec) DeepCopy() *PrivateDnsZonesMXRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesMXRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesMXRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesMXRecord_STATUS) { *out = *in @@ -1298,6 +1490,11 @@ func (in *PrivateDnsZonesMXRecord_Spec) DeepCopyInto(out *PrivateDnsZonesMXRecor (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesMXRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1412,6 +1609,50 @@ func (in *PrivateDnsZonesPTRRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesPTRRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesPTRRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesPTRRecordOperatorSpec. +func (in *PrivateDnsZonesPTRRecordOperatorSpec) DeepCopy() *PrivateDnsZonesPTRRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesPTRRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesPTRRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesPTRRecord_STATUS) { *out = *in @@ -1576,6 +1817,11 @@ func (in *PrivateDnsZonesPTRRecord_Spec) DeepCopyInto(out *PrivateDnsZonesPTRRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesPTRRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1690,6 +1936,50 @@ func (in *PrivateDnsZonesSRVRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesSRVRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesSRVRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesSRVRecordOperatorSpec. +func (in *PrivateDnsZonesSRVRecordOperatorSpec) DeepCopy() *PrivateDnsZonesSRVRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesSRVRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesSRVRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesSRVRecord_STATUS) { *out = *in @@ -1854,6 +2144,11 @@ func (in *PrivateDnsZonesSRVRecord_Spec) DeepCopyInto(out *PrivateDnsZonesSRVRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesSRVRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1968,6 +2263,50 @@ func (in *PrivateDnsZonesTXTRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesTXTRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesTXTRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesTXTRecordOperatorSpec. +func (in *PrivateDnsZonesTXTRecordOperatorSpec) DeepCopy() *PrivateDnsZonesTXTRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesTXTRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesTXTRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesTXTRecord_STATUS) { *out = *in @@ -2132,6 +2471,11 @@ func (in *PrivateDnsZonesTXTRecord_Spec) DeepCopyInto(out *PrivateDnsZonesTXTRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesTXTRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2246,6 +2590,50 @@ func (in *PrivateDnsZonesVirtualNetworkLinkList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) DeepCopyInto(out *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesVirtualNetworkLinkOperatorSpec. +func (in *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) DeepCopy() *PrivateDnsZonesVirtualNetworkLinkOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesVirtualNetworkLinkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesVirtualNetworkLink_STATUS) DeepCopyInto(out *PrivateDnsZonesVirtualNetworkLink_STATUS) { *out = *in @@ -2340,6 +2728,11 @@ func (in *PrivateDnsZonesVirtualNetworkLink_Spec) DeepCopyInto(out *PrivateDnsZo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesVirtualNetworkLinkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20200601/structure.txt b/v2/api/network/v1api20200601/structure.txt index df950cab0e8..ae4c7b14c31 100644 --- a/v2/api/network/v1api20200601/structure.txt +++ b/v2/api/network/v1api20200601/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-06-01" PrivateDnsZonesAAAARecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -18,6 +18,9 @@ PrivateDnsZonesAAAARecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -75,7 +78,7 @@ PrivateDnsZonesAAAARecord: Resource └── Type: *string PrivateDnsZonesARecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -88,6 +91,9 @@ PrivateDnsZonesARecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -145,7 +151,7 @@ PrivateDnsZonesARecord: Resource └── Type: *string PrivateDnsZonesCNAMERecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -158,6 +164,9 @@ PrivateDnsZonesCNAMERecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -215,7 +224,7 @@ PrivateDnsZonesCNAMERecord: Resource └── Type: *string PrivateDnsZonesMXRecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -228,6 +237,9 @@ PrivateDnsZonesMXRecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -285,7 +297,7 @@ PrivateDnsZonesMXRecord: Resource └── Type: *string PrivateDnsZonesPTRRecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -298,6 +310,9 @@ PrivateDnsZonesPTRRecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -355,7 +370,7 @@ PrivateDnsZonesPTRRecord: Resource └── Type: *string PrivateDnsZonesSRVRecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -368,6 +383,9 @@ PrivateDnsZonesSRVRecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -425,7 +443,7 @@ PrivateDnsZonesSRVRecord: Resource └── Type: *string PrivateDnsZonesTXTRecord: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ARecords: Object (1 property)[] │ │ └── Ipv4Address: *string │ ├── AaaaRecords: Object (1 property)[] @@ -438,6 +456,9 @@ PrivateDnsZonesTXTRecord: Resource │ ├── MxRecords: Object (2 properties)[] │ │ ├── Exchange: *string │ │ └── Preference: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PtrRecords: Object (1 property)[] │ │ └── Ptrdname: *string @@ -495,10 +516,13 @@ PrivateDnsZonesTXTRecord: Resource └── Type: *string PrivateDnsZonesVirtualNetworkLink: Resource ├── Owner: PrivateDnsZone -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Etag: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RegistrationEnabled: *bool │ ├── Tags: map[string]string diff --git a/v2/api/network/v1api20200601/zz_generated.deepcopy.go b/v2/api/network/v1api20200601/zz_generated.deepcopy.go index e8308827950..753f911dfc9 100644 --- a/v2/api/network/v1api20200601/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20200601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20200601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -244,6 +245,43 @@ func (in *PrivateDnsZonesAAAARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesAAAARecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesAAAARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesAAAARecordOperatorSpec. +func (in *PrivateDnsZonesAAAARecordOperatorSpec) DeepCopy() *PrivateDnsZonesAAAARecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesAAAARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesAAAARecord_STATUS) DeepCopyInto(out *PrivateDnsZonesAAAARecord_STATUS) { *out = *in @@ -401,6 +439,11 @@ func (in *PrivateDnsZonesAAAARecord_Spec) DeepCopyInto(out *PrivateDnsZonesAAAAR (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesAAAARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -508,6 +551,43 @@ func (in *PrivateDnsZonesARecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesARecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesARecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesARecordOperatorSpec. +func (in *PrivateDnsZonesARecordOperatorSpec) DeepCopy() *PrivateDnsZonesARecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesARecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesARecord_STATUS) DeepCopyInto(out *PrivateDnsZonesARecord_STATUS) { *out = *in @@ -665,6 +745,11 @@ func (in *PrivateDnsZonesARecord_Spec) DeepCopyInto(out *PrivateDnsZonesARecord_ (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesARecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -772,6 +857,43 @@ func (in *PrivateDnsZonesCNAMERecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesCNAMERecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesCNAMERecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesCNAMERecordOperatorSpec. +func (in *PrivateDnsZonesCNAMERecordOperatorSpec) DeepCopy() *PrivateDnsZonesCNAMERecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesCNAMERecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesCNAMERecord_STATUS) DeepCopyInto(out *PrivateDnsZonesCNAMERecord_STATUS) { *out = *in @@ -929,6 +1051,11 @@ func (in *PrivateDnsZonesCNAMERecord_Spec) DeepCopyInto(out *PrivateDnsZonesCNAM (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesCNAMERecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1036,6 +1163,43 @@ func (in *PrivateDnsZonesMXRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesMXRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesMXRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesMXRecordOperatorSpec. +func (in *PrivateDnsZonesMXRecordOperatorSpec) DeepCopy() *PrivateDnsZonesMXRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesMXRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesMXRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesMXRecord_STATUS) { *out = *in @@ -1193,6 +1357,11 @@ func (in *PrivateDnsZonesMXRecord_Spec) DeepCopyInto(out *PrivateDnsZonesMXRecor (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesMXRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1300,6 +1469,43 @@ func (in *PrivateDnsZonesPTRRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesPTRRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesPTRRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesPTRRecordOperatorSpec. +func (in *PrivateDnsZonesPTRRecordOperatorSpec) DeepCopy() *PrivateDnsZonesPTRRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesPTRRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesPTRRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesPTRRecord_STATUS) { *out = *in @@ -1457,6 +1663,11 @@ func (in *PrivateDnsZonesPTRRecord_Spec) DeepCopyInto(out *PrivateDnsZonesPTRRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesPTRRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1564,6 +1775,43 @@ func (in *PrivateDnsZonesSRVRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesSRVRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesSRVRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesSRVRecordOperatorSpec. +func (in *PrivateDnsZonesSRVRecordOperatorSpec) DeepCopy() *PrivateDnsZonesSRVRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesSRVRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesSRVRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesSRVRecord_STATUS) { *out = *in @@ -1721,6 +1969,11 @@ func (in *PrivateDnsZonesSRVRecord_Spec) DeepCopyInto(out *PrivateDnsZonesSRVRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesSRVRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1828,6 +2081,43 @@ func (in *PrivateDnsZonesTXTRecordList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesTXTRecordOperatorSpec) DeepCopyInto(out *PrivateDnsZonesTXTRecordOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesTXTRecordOperatorSpec. +func (in *PrivateDnsZonesTXTRecordOperatorSpec) DeepCopy() *PrivateDnsZonesTXTRecordOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesTXTRecordOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesTXTRecord_STATUS) DeepCopyInto(out *PrivateDnsZonesTXTRecord_STATUS) { *out = *in @@ -1985,6 +2275,11 @@ func (in *PrivateDnsZonesTXTRecord_Spec) DeepCopyInto(out *PrivateDnsZonesTXTRec (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesTXTRecordOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2092,6 +2387,43 @@ func (in *PrivateDnsZonesVirtualNetworkLinkList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) DeepCopyInto(out *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateDnsZonesVirtualNetworkLinkOperatorSpec. +func (in *PrivateDnsZonesVirtualNetworkLinkOperatorSpec) DeepCopy() *PrivateDnsZonesVirtualNetworkLinkOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateDnsZonesVirtualNetworkLinkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateDnsZonesVirtualNetworkLink_STATUS) DeepCopyInto(out *PrivateDnsZonesVirtualNetworkLink_STATUS) { *out = *in @@ -2179,6 +2511,11 @@ func (in *PrivateDnsZonesVirtualNetworkLink_Spec) DeepCopyInto(out *PrivateDnsZo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateDnsZonesVirtualNetworkLinkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20201101/load_balancer_types_gen.go b/v2/api/network/v1api20201101/load_balancer_types_gen.go index c0a82ab40cc..bc3520451ed 100644 --- a/v2/api/network/v1api20201101/load_balancer_types_gen.go +++ b/v2/api/network/v1api20201101/load_balancer_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (balancer *LoadBalancer) defaultAzureName() { // defaultImpl applies the code generated defaults to the LoadBalancer resource func (balancer *LoadBalancer) defaultImpl() { balancer.defaultAzureName() } +var _ configmaps.Exporter = &LoadBalancer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (balancer *LoadBalancer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if balancer.Spec.OperatorSpec == nil { + return nil + } + return balancer.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &LoadBalancer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (balancer *LoadBalancer) SecretDestinationExpressions() []*core.DestinationExpression { + if balancer.Spec.OperatorSpec == nil { + return nil + } + return balancer.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &LoadBalancer{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (balancer *LoadBalancer) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (balancer *LoadBalancer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){balancer.validateResourceReferences, balancer.validateOwnerReference} + return []func() (admission.Warnings, error){balancer.validateResourceReferences, balancer.validateOwnerReference, balancer.validateSecretDestinations, balancer.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (balancer *LoadBalancer) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return balancer.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return balancer.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return balancer.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (balancer *LoadBalancer) validateConfigMapDestinations() (admission.Warnings, error) { + if balancer.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(balancer, nil, balancer.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (balancer *LoadBalancer) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (balancer *LoadBalancer) validateSecretDestinations() (admission.Warnings, error) { + if balancer.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(balancer, nil, balancer.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (balancer *LoadBalancer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*LoadBalancer) @@ -363,6 +408,10 @@ type LoadBalancer_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *LoadBalancerOperatorSpec `json:"operatorSpec,omitempty"` + // OutboundRules: The outbound rules. OutboundRules []OutboundRule `json:"outboundRules,omitempty"` @@ -587,6 +636,8 @@ func (balancer *LoadBalancer_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn balancer.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "OutboundRules": // copying flattened property: if typedInput.Properties != nil { @@ -803,6 +854,18 @@ func (balancer *LoadBalancer_Spec) AssignProperties_From_LoadBalancer_Spec(sourc // Location balancer.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec LoadBalancerOperatorSpec + err := operatorSpec.AssignProperties_From_LoadBalancerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_LoadBalancerOperatorSpec() to populate field OperatorSpec") + } + balancer.OperatorSpec = &operatorSpec + } else { + balancer.OperatorSpec = nil + } + // OutboundRules if source.OutboundRules != nil { outboundRuleList := make([]OutboundRule, len(source.OutboundRules)) @@ -979,6 +1042,18 @@ func (balancer *LoadBalancer_Spec) AssignProperties_To_LoadBalancer_Spec(destina // Location destination.Location = genruntime.ClonePointerToString(balancer.Location) + // OperatorSpec + if balancer.OperatorSpec != nil { + var operatorSpec storage.LoadBalancerOperatorSpec + err := balancer.OperatorSpec.AssignProperties_To_LoadBalancerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_LoadBalancerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = balancer.OriginalVersion() @@ -5123,6 +5198,110 @@ func (embedded *InboundNatRule_STATUS_LoadBalancer_SubResourceEmbedded) AssignPr return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type LoadBalancerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_LoadBalancerOperatorSpec populates our LoadBalancerOperatorSpec from the provided source LoadBalancerOperatorSpec +func (operator *LoadBalancerOperatorSpec) AssignProperties_From_LoadBalancerOperatorSpec(source *storage.LoadBalancerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_LoadBalancerOperatorSpec populates the provided destination LoadBalancerOperatorSpec from our LoadBalancerOperatorSpec +func (operator *LoadBalancerOperatorSpec) AssignProperties_To_LoadBalancerOperatorSpec(destination *storage.LoadBalancerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // SKU of a load balancer. type LoadBalancerSku struct { // Name: Name of a load balancer SKU. diff --git a/v2/api/network/v1api20201101/load_balancer_types_gen_test.go b/v2/api/network/v1api20201101/load_balancer_types_gen_test.go index e4e483dfc7c..39ff8f8a10f 100644 --- a/v2/api/network/v1api20201101/load_balancer_types_gen_test.go +++ b/v2/api/network/v1api20201101/load_balancer_types_gen_test.go @@ -1626,6 +1626,103 @@ func AddRelatedPropertyGeneratorsForLoadBalancerBackendAddress_STATUS(gens map[s gens["VirtualNetwork"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_LoadBalancerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from LoadBalancerOperatorSpec to LoadBalancerOperatorSpec via AssignProperties_To_LoadBalancerOperatorSpec & AssignProperties_From_LoadBalancerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForLoadBalancerOperatorSpec, LoadBalancerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForLoadBalancerOperatorSpec tests if a specific instance of LoadBalancerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForLoadBalancerOperatorSpec(subject LoadBalancerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.LoadBalancerOperatorSpec + err := copied.AssignProperties_To_LoadBalancerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual LoadBalancerOperatorSpec + err = actual.AssignProperties_From_LoadBalancerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_LoadBalancerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of LoadBalancerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForLoadBalancerOperatorSpec, LoadBalancerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForLoadBalancerOperatorSpec runs a test to see if a specific instance of LoadBalancerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForLoadBalancerOperatorSpec(subject LoadBalancerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual LoadBalancerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of LoadBalancerOperatorSpec instances for property testing - lazily instantiated by +// LoadBalancerOperatorSpecGenerator() +var loadBalancerOperatorSpecGenerator gopter.Gen + +// LoadBalancerOperatorSpecGenerator returns a generator of LoadBalancerOperatorSpec instances for property testing. +func LoadBalancerOperatorSpecGenerator() gopter.Gen { + if loadBalancerOperatorSpecGenerator != nil { + return loadBalancerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + loadBalancerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(LoadBalancerOperatorSpec{}), generators) + + return loadBalancerOperatorSpecGenerator +} + func Test_LoadBalancerSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2094,6 +2191,7 @@ func AddRelatedPropertyGeneratorsForLoadBalancer_Spec(gens map[string]gopter.Gen gens["InboundNatPools"] = gen.SliceOf(InboundNatPoolGenerator()) gens["InboundNatRules"] = gen.SliceOf(InboundNatRule_LoadBalancer_SubResourceEmbeddedGenerator()) gens["LoadBalancingRules"] = gen.SliceOf(LoadBalancingRuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(LoadBalancerOperatorSpecGenerator()) gens["OutboundRules"] = gen.SliceOf(OutboundRuleGenerator()) gens["Probes"] = gen.SliceOf(ProbeGenerator()) gens["Sku"] = gen.PtrOf(LoadBalancerSkuGenerator()) diff --git a/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen.go b/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen.go index b8a87e70a61..89458ee9e4f 100644 --- a/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen.go +++ b/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *LoadBalancersInboundNatRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the LoadBalancersInboundNatRule resource func (rule *LoadBalancersInboundNatRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &LoadBalancersInboundNatRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *LoadBalancersInboundNatRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &LoadBalancersInboundNatRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *LoadBalancersInboundNatRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &LoadBalancersInboundNatRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *LoadBalancersInboundNatRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *LoadBalancersInboundNatRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *LoadBalancersInboundNatRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *LoadBalancersInboundNatRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *LoadBalancersInboundNatRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *LoadBalancersInboundNatRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *LoadBalancersInboundNatRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*LoadBalancersInboundNatRule) @@ -353,6 +398,10 @@ type LoadBalancersInboundNatRule_Spec struct { // default value is 4 minutes. This element is only used when the protocol is set to TCP. IdleTimeoutInMinutes *int `json:"idleTimeoutInMinutes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *LoadBalancersInboundNatRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -496,6 +545,8 @@ func (rule *LoadBalancersInboundNatRule_Spec) PopulateFromARM(owner genruntime.A } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -610,6 +661,18 @@ func (rule *LoadBalancersInboundNatRule_Spec) AssignProperties_From_LoadBalancer // IdleTimeoutInMinutes rule.IdleTimeoutInMinutes = genruntime.ClonePointerToInt(source.IdleTimeoutInMinutes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec LoadBalancersInboundNatRuleOperatorSpec + err := operatorSpec.AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -676,6 +739,18 @@ func (rule *LoadBalancersInboundNatRule_Spec) AssignProperties_To_LoadBalancersI // IdleTimeoutInMinutes destination.IdleTimeoutInMinutes = genruntime.ClonePointerToInt(rule.IdleTimeoutInMinutes) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.LoadBalancersInboundNatRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1193,6 +1268,110 @@ func (rule *LoadBalancersInboundNatRule_STATUS) AssignProperties_To_LoadBalancer return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type LoadBalancersInboundNatRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec populates our LoadBalancersInboundNatRuleOperatorSpec from the provided source LoadBalancersInboundNatRuleOperatorSpec +func (operator *LoadBalancersInboundNatRuleOperatorSpec) AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec(source *storage.LoadBalancersInboundNatRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec populates the provided destination LoadBalancersInboundNatRuleOperatorSpec from our LoadBalancersInboundNatRuleOperatorSpec +func (operator *LoadBalancersInboundNatRuleOperatorSpec) AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec(destination *storage.LoadBalancersInboundNatRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // IPConfiguration in a network interface. type NetworkInterfaceIPConfiguration_STATUS_LoadBalancers_InboundNatRule_SubResourceEmbedded struct { // Id: Resource ID. diff --git a/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen_test.go b/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen_test.go index bf245979b43..b6e775237e3 100644 --- a/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen_test.go +++ b/v2/api/network/v1api20201101/load_balancers_inbound_nat_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule(gens map[string] gens["Status"] = LoadBalancersInboundNatRule_STATUSGenerator() } +func Test_LoadBalancersInboundNatRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from LoadBalancersInboundNatRuleOperatorSpec to LoadBalancersInboundNatRuleOperatorSpec via AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec & AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForLoadBalancersInboundNatRuleOperatorSpec, LoadBalancersInboundNatRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForLoadBalancersInboundNatRuleOperatorSpec tests if a specific instance of LoadBalancersInboundNatRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForLoadBalancersInboundNatRuleOperatorSpec(subject LoadBalancersInboundNatRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.LoadBalancersInboundNatRuleOperatorSpec + err := copied.AssignProperties_To_LoadBalancersInboundNatRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual LoadBalancersInboundNatRuleOperatorSpec + err = actual.AssignProperties_From_LoadBalancersInboundNatRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_LoadBalancersInboundNatRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of LoadBalancersInboundNatRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec, LoadBalancersInboundNatRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec runs a test to see if a specific instance of LoadBalancersInboundNatRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec(subject LoadBalancersInboundNatRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual LoadBalancersInboundNatRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of LoadBalancersInboundNatRuleOperatorSpec instances for property testing - lazily instantiated by +// LoadBalancersInboundNatRuleOperatorSpecGenerator() +var loadBalancersInboundNatRuleOperatorSpecGenerator gopter.Gen + +// LoadBalancersInboundNatRuleOperatorSpecGenerator returns a generator of LoadBalancersInboundNatRuleOperatorSpec instances for property testing. +func LoadBalancersInboundNatRuleOperatorSpecGenerator() gopter.Gen { + if loadBalancersInboundNatRuleOperatorSpecGenerator != nil { + return loadBalancersInboundNatRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + loadBalancersInboundNatRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(LoadBalancersInboundNatRuleOperatorSpec{}), generators) + + return loadBalancersInboundNatRuleOperatorSpecGenerator +} + func Test_LoadBalancersInboundNatRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -418,6 +515,7 @@ func AddIndependentPropertyGeneratorsForLoadBalancersInboundNatRule_Spec(gens ma // AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule_Spec(gens map[string]gopter.Gen) { gens["FrontendIPConfiguration"] = gen.PtrOf(SubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(LoadBalancersInboundNatRuleOperatorSpecGenerator()) } func Test_NetworkInterfaceIPConfiguration_STATUS_LoadBalancers_InboundNatRule_SubResourceEmbedded_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/network/v1api20201101/network_interface_types_gen.go b/v2/api/network/v1api20201101/network_interface_types_gen.go index 57ea2ad5238..c88189e9695 100644 --- a/v2/api/network/v1api20201101/network_interface_types_gen.go +++ b/v2/api/network/v1api20201101/network_interface_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (networkInterface *NetworkInterface) defaultAzureName() { // defaultImpl applies the code generated defaults to the NetworkInterface resource func (networkInterface *NetworkInterface) defaultImpl() { networkInterface.defaultAzureName() } +var _ configmaps.Exporter = &NetworkInterface{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (networkInterface *NetworkInterface) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if networkInterface.Spec.OperatorSpec == nil { + return nil + } + return networkInterface.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkInterface{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (networkInterface *NetworkInterface) SecretDestinationExpressions() []*core.DestinationExpression { + if networkInterface.Spec.OperatorSpec == nil { + return nil + } + return networkInterface.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NetworkInterface{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (networkInterface *NetworkInterface) ValidateUpdate(old runtime.Object) (ad // createValidations validates the creation of the resource func (networkInterface *NetworkInterface) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){networkInterface.validateResourceReferences, networkInterface.validateOwnerReference} + return []func() (admission.Warnings, error){networkInterface.validateResourceReferences, networkInterface.validateOwnerReference, networkInterface.validateSecretDestinations, networkInterface.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (networkInterface *NetworkInterface) updateValidations() []func(old runtime func(old runtime.Object) (admission.Warnings, error) { return networkInterface.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return networkInterface.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return networkInterface.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (networkInterface *NetworkInterface) validateConfigMapDestinations() (admission.Warnings, error) { + if networkInterface.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(networkInterface, nil, networkInterface.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (networkInterface *NetworkInterface) validateResourceReferences() (admissio return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (networkInterface *NetworkInterface) validateSecretDestinations() (admission.Warnings, error) { + if networkInterface.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(networkInterface, nil, networkInterface.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (networkInterface *NetworkInterface) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NetworkInterface) @@ -354,6 +399,10 @@ type NetworkInterface_Spec struct { // NicType: Type of Network Interface resource. NicType *NetworkInterfacePropertiesFormat_NicType `json:"nicType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NetworkInterfaceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -563,6 +612,8 @@ func (networkInterface *NetworkInterface_Spec) PopulateFromARM(owner genruntime. } } + // no assignment for property "OperatorSpec" + // Set property "Owner": networkInterface.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -733,6 +784,18 @@ func (networkInterface *NetworkInterface_Spec) AssignProperties_From_NetworkInte networkInterface.NicType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NetworkInterfaceOperatorSpec + err := operatorSpec.AssignProperties_From_NetworkInterfaceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NetworkInterfaceOperatorSpec() to populate field OperatorSpec") + } + networkInterface.OperatorSpec = &operatorSpec + } else { + networkInterface.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -849,6 +912,18 @@ func (networkInterface *NetworkInterface_Spec) AssignProperties_To_NetworkInterf destination.NicType = nil } + // OperatorSpec + if networkInterface.OperatorSpec != nil { + var operatorSpec storage.NetworkInterfaceOperatorSpec + err := networkInterface.OperatorSpec.AssignProperties_To_NetworkInterfaceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NetworkInterfaceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = networkInterface.OriginalVersion() @@ -3431,6 +3506,110 @@ func (embedded *NetworkInterfaceIPConfiguration_STATUS_NetworkInterface_SubResou return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkInterfaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NetworkInterfaceOperatorSpec populates our NetworkInterfaceOperatorSpec from the provided source NetworkInterfaceOperatorSpec +func (operator *NetworkInterfaceOperatorSpec) AssignProperties_From_NetworkInterfaceOperatorSpec(source *storage.NetworkInterfaceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NetworkInterfaceOperatorSpec populates the provided destination NetworkInterfaceOperatorSpec from our NetworkInterfaceOperatorSpec +func (operator *NetworkInterfaceOperatorSpec) AssignProperties_To_NetworkInterfaceOperatorSpec(destination *storage.NetworkInterfaceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type NetworkInterfacePropertiesFormat_MigrationPhase_STATUS string const ( diff --git a/v2/api/network/v1api20201101/network_interface_types_gen_test.go b/v2/api/network/v1api20201101/network_interface_types_gen_test.go index 0daae15e3ef..9719ce414ae 100644 --- a/v2/api/network/v1api20201101/network_interface_types_gen_test.go +++ b/v2/api/network/v1api20201101/network_interface_types_gen_test.go @@ -1544,6 +1544,103 @@ func AddRelatedPropertyGeneratorsForNetworkInterfaceIPConfiguration_STATUS_Netwo gens["VirtualNetworkTaps"] = gen.SliceOf(VirtualNetworkTap_STATUS_NetworkInterface_SubResourceEmbeddedGenerator()) } +func Test_NetworkInterfaceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NetworkInterfaceOperatorSpec to NetworkInterfaceOperatorSpec via AssignProperties_To_NetworkInterfaceOperatorSpec & AssignProperties_From_NetworkInterfaceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNetworkInterfaceOperatorSpec, NetworkInterfaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNetworkInterfaceOperatorSpec tests if a specific instance of NetworkInterfaceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNetworkInterfaceOperatorSpec(subject NetworkInterfaceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NetworkInterfaceOperatorSpec + err := copied.AssignProperties_To_NetworkInterfaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NetworkInterfaceOperatorSpec + err = actual.AssignProperties_From_NetworkInterfaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NetworkInterfaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkInterfaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkInterfaceOperatorSpec, NetworkInterfaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkInterfaceOperatorSpec runs a test to see if a specific instance of NetworkInterfaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkInterfaceOperatorSpec(subject NetworkInterfaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkInterfaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkInterfaceOperatorSpec instances for property testing - lazily instantiated by +// NetworkInterfaceOperatorSpecGenerator() +var networkInterfaceOperatorSpecGenerator gopter.Gen + +// NetworkInterfaceOperatorSpecGenerator returns a generator of NetworkInterfaceOperatorSpec instances for property testing. +func NetworkInterfaceOperatorSpecGenerator() gopter.Gen { + if networkInterfaceOperatorSpecGenerator != nil { + return networkInterfaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkInterfaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkInterfaceOperatorSpec{}), generators) + + return networkInterfaceOperatorSpecGenerator +} + func Test_NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1922,6 +2019,7 @@ func AddRelatedPropertyGeneratorsForNetworkInterface_Spec(gens map[string]gopter gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpConfigurations"] = gen.SliceOf(NetworkInterfaceIPConfiguration_NetworkInterface_SubResourceEmbeddedGenerator()) gens["NetworkSecurityGroup"] = gen.PtrOf(NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NetworkInterfaceOperatorSpecGenerator()) gens["PrivateLinkService"] = gen.PtrOf(PrivateLinkServiceSpecGenerator()) } diff --git a/v2/api/network/v1api20201101/network_security_group_types_gen.go b/v2/api/network/v1api20201101/network_security_group_types_gen.go index 030eedb8070..bbc735ad6ec 100644 --- a/v2/api/network/v1api20201101/network_security_group_types_gen.go +++ b/v2/api/network/v1api20201101/network_security_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *NetworkSecurityGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the NetworkSecurityGroup resource func (group *NetworkSecurityGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &NetworkSecurityGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *NetworkSecurityGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkSecurityGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *NetworkSecurityGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NetworkSecurityGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *NetworkSecurityGroup) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (group *NetworkSecurityGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *NetworkSecurityGroup) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *NetworkSecurityGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *NetworkSecurityGroup) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *NetworkSecurityGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *NetworkSecurityGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NetworkSecurityGroup) @@ -333,6 +378,10 @@ type NetworkSecurityGroup_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NetworkSecurityGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -394,6 +443,8 @@ func (group *NetworkSecurityGroup_Spec) PopulateFromARM(owner genruntime.Arbitra group.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -471,6 +522,18 @@ func (group *NetworkSecurityGroup_Spec) AssignProperties_From_NetworkSecurityGro // Location group.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NetworkSecurityGroupOperatorSpec + err := operatorSpec.AssignProperties_From_NetworkSecurityGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NetworkSecurityGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -497,6 +560,18 @@ func (group *NetworkSecurityGroup_Spec) AssignProperties_To_NetworkSecurityGroup // Location destination.Location = genruntime.ClonePointerToString(group.Location) + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.NetworkSecurityGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_NetworkSecurityGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NetworkSecurityGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -1115,6 +1190,110 @@ func (embedded *NetworkInterface_STATUS_NetworkSecurityGroup_SubResourceEmbedded return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkSecurityGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NetworkSecurityGroupOperatorSpec populates our NetworkSecurityGroupOperatorSpec from the provided source NetworkSecurityGroupOperatorSpec +func (operator *NetworkSecurityGroupOperatorSpec) AssignProperties_From_NetworkSecurityGroupOperatorSpec(source *storage.NetworkSecurityGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NetworkSecurityGroupOperatorSpec populates the provided destination NetworkSecurityGroupOperatorSpec from our NetworkSecurityGroupOperatorSpec +func (operator *NetworkSecurityGroupOperatorSpec) AssignProperties_To_NetworkSecurityGroupOperatorSpec(destination *storage.NetworkSecurityGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Network security rule. type SecurityRule_STATUS struct { // Id: Resource ID. diff --git a/v2/api/network/v1api20201101/network_security_group_types_gen_test.go b/v2/api/network/v1api20201101/network_security_group_types_gen_test.go index f134b3f3341..f4d488d388c 100644 --- a/v2/api/network/v1api20201101/network_security_group_types_gen_test.go +++ b/v2/api/network/v1api20201101/network_security_group_types_gen_test.go @@ -370,6 +370,103 @@ func AddRelatedPropertyGeneratorsForNetworkSecurityGroup(gens map[string]gopter. gens["Status"] = NetworkSecurityGroup_STATUS_NetworkSecurityGroup_SubResourceEmbeddedGenerator() } +func Test_NetworkSecurityGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NetworkSecurityGroupOperatorSpec to NetworkSecurityGroupOperatorSpec via AssignProperties_To_NetworkSecurityGroupOperatorSpec & AssignProperties_From_NetworkSecurityGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNetworkSecurityGroupOperatorSpec, NetworkSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNetworkSecurityGroupOperatorSpec tests if a specific instance of NetworkSecurityGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNetworkSecurityGroupOperatorSpec(subject NetworkSecurityGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NetworkSecurityGroupOperatorSpec + err := copied.AssignProperties_To_NetworkSecurityGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NetworkSecurityGroupOperatorSpec + err = actual.AssignProperties_From_NetworkSecurityGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NetworkSecurityGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkSecurityGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec, NetworkSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec runs a test to see if a specific instance of NetworkSecurityGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec(subject NetworkSecurityGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkSecurityGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkSecurityGroupOperatorSpec instances for property testing - lazily instantiated by +// NetworkSecurityGroupOperatorSpecGenerator() +var networkSecurityGroupOperatorSpecGenerator gopter.Gen + +// NetworkSecurityGroupOperatorSpecGenerator returns a generator of NetworkSecurityGroupOperatorSpec instances for property testing. +func NetworkSecurityGroupOperatorSpecGenerator() gopter.Gen { + if networkSecurityGroupOperatorSpecGenerator != nil { + return networkSecurityGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkSecurityGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroupOperatorSpec{}), generators) + + return networkSecurityGroupOperatorSpecGenerator +} + func Test_NetworkSecurityGroup_STATUS_NetworkSecurityGroup_SubResourceEmbedded_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -589,6 +686,9 @@ func RunJSONSerializationTestForNetworkSecurityGroup_Spec(subject NetworkSecurit var networkSecurityGroup_SpecGenerator gopter.Gen // NetworkSecurityGroup_SpecGenerator returns a generator of NetworkSecurityGroup_Spec instances for property testing. +// We first initialize networkSecurityGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NetworkSecurityGroup_SpecGenerator() gopter.Gen { if networkSecurityGroup_SpecGenerator != nil { return networkSecurityGroup_SpecGenerator @@ -598,6 +698,12 @@ func NetworkSecurityGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) networkSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) + AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) + networkSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroup_Spec{}), generators) + return networkSecurityGroup_SpecGenerator } @@ -610,6 +716,11 @@ func AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(gens map[strin gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NetworkSecurityGroupOperatorSpecGenerator()) +} + func Test_SecurityRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen.go b/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen.go index 571a065ca03..9e14595c5b9 100644 --- a/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen.go +++ b/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *NetworkSecurityGroupsSecurityRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NetworkSecurityGroupsSecurityRule resource func (rule *NetworkSecurityGroupsSecurityRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NetworkSecurityGroupsSecurityRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NetworkSecurityGroupsSecurityRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkSecurityGroupsSecurityRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NetworkSecurityGroupsSecurityRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NetworkSecurityGroupsSecurityRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *NetworkSecurityGroupsSecurityRule) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (rule *NetworkSecurityGroupsSecurityRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *NetworkSecurityGroupsSecurityRule) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NetworkSecurityGroupsSecurityRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *NetworkSecurityGroupsSecurityRule) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *NetworkSecurityGroupsSecurityRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *NetworkSecurityGroupsSecurityRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NetworkSecurityGroupsSecurityRule) @@ -358,6 +403,10 @@ type NetworkSecurityGroupsSecurityRule_Spec struct { // Direction: The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic. Direction *SecurityRuleDirection `json:"direction,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NetworkSecurityGroupsSecurityRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -585,6 +634,8 @@ func (rule *NetworkSecurityGroupsSecurityRule_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -769,6 +820,18 @@ func (rule *NetworkSecurityGroupsSecurityRule_Spec) AssignProperties_From_Networ rule.Direction = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NetworkSecurityGroupsSecurityRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -880,6 +943,18 @@ func (rule *NetworkSecurityGroupsSecurityRule_Spec) AssignProperties_To_NetworkS destination.Direction = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NetworkSecurityGroupsSecurityRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1782,6 +1857,110 @@ func (embedded *ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkSecurityGroupsSecurityRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec populates our NetworkSecurityGroupsSecurityRuleOperatorSpec from the provided source NetworkSecurityGroupsSecurityRuleOperatorSpec +func (operator *NetworkSecurityGroupsSecurityRuleOperatorSpec) AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec(source *storage.NetworkSecurityGroupsSecurityRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec populates the provided destination NetworkSecurityGroupsSecurityRuleOperatorSpec from our NetworkSecurityGroupsSecurityRuleOperatorSpec +func (operator *NetworkSecurityGroupsSecurityRuleOperatorSpec) AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec(destination *storage.NetworkSecurityGroupsSecurityRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Whether network traffic is allowed or denied. // +kubebuilder:validation:Enum={"Allow","Deny"} type SecurityRuleAccess string diff --git a/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen_test.go b/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen_test.go index 8dc26ed3c9b..a6a0dafea2c 100644 --- a/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen_test.go +++ b/v2/api/network/v1api20201101/network_security_groups_security_rule_types_gen_test.go @@ -367,6 +367,103 @@ func AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule(gens map[s gens["Status"] = NetworkSecurityGroupsSecurityRule_STATUSGenerator() } +func Test_NetworkSecurityGroupsSecurityRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NetworkSecurityGroupsSecurityRuleOperatorSpec to NetworkSecurityGroupsSecurityRuleOperatorSpec via AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec & AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNetworkSecurityGroupsSecurityRuleOperatorSpec, NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNetworkSecurityGroupsSecurityRuleOperatorSpec tests if a specific instance of NetworkSecurityGroupsSecurityRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNetworkSecurityGroupsSecurityRuleOperatorSpec(subject NetworkSecurityGroupsSecurityRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NetworkSecurityGroupsSecurityRuleOperatorSpec + err := copied.AssignProperties_To_NetworkSecurityGroupsSecurityRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NetworkSecurityGroupsSecurityRuleOperatorSpec + err = actual.AssignProperties_From_NetworkSecurityGroupsSecurityRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NetworkSecurityGroupsSecurityRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkSecurityGroupsSecurityRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec, NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec runs a test to see if a specific instance of NetworkSecurityGroupsSecurityRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec(subject NetworkSecurityGroupsSecurityRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkSecurityGroupsSecurityRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkSecurityGroupsSecurityRuleOperatorSpec instances for property testing - lazily instantiated by +// NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator() +var networkSecurityGroupsSecurityRuleOperatorSpecGenerator gopter.Gen + +// NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator returns a generator of NetworkSecurityGroupsSecurityRuleOperatorSpec instances for property testing. +func NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator() gopter.Gen { + if networkSecurityGroupsSecurityRuleOperatorSpecGenerator != nil { + return networkSecurityGroupsSecurityRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkSecurityGroupsSecurityRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroupsSecurityRuleOperatorSpec{}), generators) + + return networkSecurityGroupsSecurityRuleOperatorSpecGenerator +} + func Test_NetworkSecurityGroupsSecurityRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -646,5 +743,6 @@ func AddIndependentPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec(g // AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec(gens map[string]gopter.Gen) { gens["DestinationApplicationSecurityGroups"] = gen.SliceOf(ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator()) gens["SourceApplicationSecurityGroups"] = gen.SliceOf(ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_SubResourceEmbeddedGenerator()) } diff --git a/v2/api/network/v1api20201101/public_ip_address_types_gen.go b/v2/api/network/v1api20201101/public_ip_address_types_gen.go index 4a89051b68b..6f304f88872 100644 --- a/v2/api/network/v1api20201101/public_ip_address_types_gen.go +++ b/v2/api/network/v1api20201101/public_ip_address_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (address *PublicIPAddress) defaultAzureName() { // defaultImpl applies the code generated defaults to the PublicIPAddress resource func (address *PublicIPAddress) defaultImpl() { address.defaultAzureName() } +var _ configmaps.Exporter = &PublicIPAddress{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (address *PublicIPAddress) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if address.Spec.OperatorSpec == nil { + return nil + } + return address.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PublicIPAddress{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (address *PublicIPAddress) SecretDestinationExpressions() []*core.DestinationExpression { + if address.Spec.OperatorSpec == nil { + return nil + } + return address.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PublicIPAddress{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (address *PublicIPAddress) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (address *PublicIPAddress) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){address.validateResourceReferences, address.validateOwnerReference} + return []func() (admission.Warnings, error){address.validateResourceReferences, address.validateOwnerReference, address.validateSecretDestinations, address.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (address *PublicIPAddress) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return address.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return address.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return address.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (address *PublicIPAddress) validateConfigMapDestinations() (admission.Warnings, error) { + if address.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(address, nil, address.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (address *PublicIPAddress) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (address *PublicIPAddress) validateSecretDestinations() (admission.Warnings, error) { + if address.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(address, nil, address.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (address *PublicIPAddress) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PublicIPAddress) @@ -357,6 +402,10 @@ type PublicIPAddress_Spec struct { // NatGateway: The NatGateway for the Public IP address. NatGateway *NatGatewaySpec_PublicIPAddress_SubResourceEmbedded `json:"natGateway,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PublicIPAddressOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -647,6 +696,8 @@ func (address *PublicIPAddress_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": address.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -874,6 +925,18 @@ func (address *PublicIPAddress_Spec) AssignProperties_From_PublicIPAddress_Spec( address.NatGateway = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PublicIPAddressOperatorSpec + err := operatorSpec.AssignProperties_From_PublicIPAddressOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PublicIPAddressOperatorSpec() to populate field OperatorSpec") + } + address.OperatorSpec = &operatorSpec + } else { + address.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1041,6 +1104,18 @@ func (address *PublicIPAddress_Spec) AssignProperties_To_PublicIPAddress_Spec(de destination.NatGateway = nil } + // OperatorSpec + if address.OperatorSpec != nil { + var operatorSpec storage.PublicIPAddressOperatorSpec + err := address.OperatorSpec.AssignProperties_To_PublicIPAddressOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PublicIPAddressOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = address.OriginalVersion() @@ -3007,6 +3082,110 @@ func (settings *PublicIPAddressDnsSettings_STATUS) AssignProperties_To_PublicIPA return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PublicIPAddressOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PublicIPAddressOperatorSpec populates our PublicIPAddressOperatorSpec from the provided source PublicIPAddressOperatorSpec +func (operator *PublicIPAddressOperatorSpec) AssignProperties_From_PublicIPAddressOperatorSpec(source *storage.PublicIPAddressOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PublicIPAddressOperatorSpec populates the provided destination PublicIPAddressOperatorSpec from our PublicIPAddressOperatorSpec +func (operator *PublicIPAddressOperatorSpec) AssignProperties_To_PublicIPAddressOperatorSpec(destination *storage.PublicIPAddressOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type PublicIPAddressPropertiesFormat_MigrationPhase_STATUS string const ( diff --git a/v2/api/network/v1api20201101/public_ip_address_types_gen_test.go b/v2/api/network/v1api20201101/public_ip_address_types_gen_test.go index 159de1f4940..ef39331c2b1 100644 --- a/v2/api/network/v1api20201101/public_ip_address_types_gen_test.go +++ b/v2/api/network/v1api20201101/public_ip_address_types_gen_test.go @@ -1118,6 +1118,103 @@ func AddIndependentPropertyGeneratorsForPublicIPAddressDnsSettings_STATUS(gens m gens["ReverseFqdn"] = gen.PtrOf(gen.AlphaString()) } +func Test_PublicIPAddressOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PublicIPAddressOperatorSpec to PublicIPAddressOperatorSpec via AssignProperties_To_PublicIPAddressOperatorSpec & AssignProperties_From_PublicIPAddressOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPublicIPAddressOperatorSpec, PublicIPAddressOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPublicIPAddressOperatorSpec tests if a specific instance of PublicIPAddressOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPublicIPAddressOperatorSpec(subject PublicIPAddressOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PublicIPAddressOperatorSpec + err := copied.AssignProperties_To_PublicIPAddressOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PublicIPAddressOperatorSpec + err = actual.AssignProperties_From_PublicIPAddressOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PublicIPAddressOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PublicIPAddressOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPublicIPAddressOperatorSpec, PublicIPAddressOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPublicIPAddressOperatorSpec runs a test to see if a specific instance of PublicIPAddressOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPublicIPAddressOperatorSpec(subject PublicIPAddressOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PublicIPAddressOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PublicIPAddressOperatorSpec instances for property testing - lazily instantiated by +// PublicIPAddressOperatorSpecGenerator() +var publicIPAddressOperatorSpecGenerator gopter.Gen + +// PublicIPAddressOperatorSpecGenerator returns a generator of PublicIPAddressOperatorSpec instances for property testing. +func PublicIPAddressOperatorSpecGenerator() gopter.Gen { + if publicIPAddressOperatorSpecGenerator != nil { + return publicIPAddressOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + publicIPAddressOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PublicIPAddressOperatorSpec{}), generators) + + return publicIPAddressOperatorSpecGenerator +} + func Test_PublicIPAddressSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1699,6 +1796,7 @@ func AddRelatedPropertyGeneratorsForPublicIPAddress_Spec(gens map[string]gopter. gens["IpTags"] = gen.SliceOf(IpTagGenerator()) gens["LinkedPublicIPAddress"] = gen.PtrOf(PublicIPAddressSpec_PublicIPAddress_SubResourceEmbeddedGenerator()) gens["NatGateway"] = gen.PtrOf(NatGatewaySpec_PublicIPAddress_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PublicIPAddressOperatorSpecGenerator()) gens["PublicIPPrefix"] = gen.PtrOf(SubResourceGenerator()) gens["ServicePublicIPAddress"] = gen.PtrOf(PublicIPAddressSpec_PublicIPAddress_SubResourceEmbeddedGenerator()) gens["Sku"] = gen.PtrOf(PublicIPAddressSkuGenerator()) diff --git a/v2/api/network/v1api20201101/route_table_types_gen.go b/v2/api/network/v1api20201101/route_table_types_gen.go index 7391906b23e..22fdd501412 100644 --- a/v2/api/network/v1api20201101/route_table_types_gen.go +++ b/v2/api/network/v1api20201101/route_table_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (table *RouteTable) defaultAzureName() { // defaultImpl applies the code generated defaults to the RouteTable resource func (table *RouteTable) defaultImpl() { table.defaultAzureName() } +var _ configmaps.Exporter = &RouteTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *RouteTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RouteTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *RouteTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RouteTable{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (table *RouteTable) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (table *RouteTable) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference} + return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference, table.validateSecretDestinations, table.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (table *RouteTable) updateValidations() []func(old runtime.Object) (admissi func(old runtime.Object) (admission.Warnings, error) { return table.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (table *RouteTable) validateConfigMapDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(table, nil, table.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (table *RouteTable) validateResourceReferences() (admission.Warnings, error return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (table *RouteTable) validateSecretDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(table, nil, table.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (table *RouteTable) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RouteTable) @@ -336,6 +381,10 @@ type RouteTable_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RouteTableOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -413,6 +462,8 @@ func (table *RouteTable_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRef table.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": table.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -498,6 +549,18 @@ func (table *RouteTable_Spec) AssignProperties_From_RouteTable_Spec(source *stor // Location table.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RouteTableOperatorSpec + err := operatorSpec.AssignProperties_From_RouteTableOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RouteTableOperatorSpec() to populate field OperatorSpec") + } + table.OperatorSpec = &operatorSpec + } else { + table.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -532,6 +595,18 @@ func (table *RouteTable_Spec) AssignProperties_To_RouteTable_Spec(destination *s // Location destination.Location = genruntime.ClonePointerToString(table.Location) + // OperatorSpec + if table.OperatorSpec != nil { + var operatorSpec storage.RouteTableOperatorSpec + err := table.OperatorSpec.AssignProperties_To_RouteTableOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RouteTableOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = table.OriginalVersion() @@ -860,6 +935,110 @@ func (table *RouteTable_STATUS) AssignProperties_To_RouteTable_STATUS(destinatio return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteTableOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RouteTableOperatorSpec populates our RouteTableOperatorSpec from the provided source RouteTableOperatorSpec +func (operator *RouteTableOperatorSpec) AssignProperties_From_RouteTableOperatorSpec(source *storage.RouteTableOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RouteTableOperatorSpec populates the provided destination RouteTableOperatorSpec from our RouteTableOperatorSpec +func (operator *RouteTableOperatorSpec) AssignProperties_To_RouteTableOperatorSpec(destination *storage.RouteTableOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&RouteTable{}, &RouteTableList{}) } diff --git a/v2/api/network/v1api20201101/route_table_types_gen_test.go b/v2/api/network/v1api20201101/route_table_types_gen_test.go index 88c75cbc8af..9fe3f911030 100644 --- a/v2/api/network/v1api20201101/route_table_types_gen_test.go +++ b/v2/api/network/v1api20201101/route_table_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRouteTable(gens map[string]gopter.Gen) { gens["Status"] = RouteTable_STATUSGenerator() } +func Test_RouteTableOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RouteTableOperatorSpec to RouteTableOperatorSpec via AssignProperties_To_RouteTableOperatorSpec & AssignProperties_From_RouteTableOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRouteTableOperatorSpec, RouteTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRouteTableOperatorSpec tests if a specific instance of RouteTableOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRouteTableOperatorSpec(subject RouteTableOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RouteTableOperatorSpec + err := copied.AssignProperties_To_RouteTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RouteTableOperatorSpec + err = actual.AssignProperties_From_RouteTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RouteTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteTableOperatorSpec, RouteTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteTableOperatorSpec runs a test to see if a specific instance of RouteTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteTableOperatorSpec(subject RouteTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteTableOperatorSpec instances for property testing - lazily instantiated by +// RouteTableOperatorSpecGenerator() +var routeTableOperatorSpecGenerator gopter.Gen + +// RouteTableOperatorSpecGenerator returns a generator of RouteTableOperatorSpec instances for property testing. +func RouteTableOperatorSpecGenerator() gopter.Gen { + if routeTableOperatorSpecGenerator != nil { + return routeTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteTableOperatorSpec{}), generators) + + return routeTableOperatorSpecGenerator +} + func Test_RouteTable_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -365,6 +462,9 @@ func RunJSONSerializationTestForRouteTable_Spec(subject RouteTable_Spec) string var routeTable_SpecGenerator gopter.Gen // RouteTable_SpecGenerator returns a generator of RouteTable_Spec instances for property testing. +// We first initialize routeTable_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RouteTable_SpecGenerator() gopter.Gen { if routeTable_SpecGenerator != nil { return routeTable_SpecGenerator @@ -374,6 +474,12 @@ func RouteTable_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRouteTable_Spec(generators) routeTable_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTable_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRouteTable_Spec(generators) + AddRelatedPropertyGeneratorsForRouteTable_Spec(generators) + routeTable_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTable_Spec{}), generators) + return routeTable_SpecGenerator } @@ -386,3 +492,8 @@ func AddIndependentPropertyGeneratorsForRouteTable_Spec(gens map[string]gopter.G gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRouteTable_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRouteTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RouteTableOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20201101/route_tables_route_types_gen.go b/v2/api/network/v1api20201101/route_tables_route_types_gen.go index b1e9442c340..725a245741d 100644 --- a/v2/api/network/v1api20201101/route_tables_route_types_gen.go +++ b/v2/api/network/v1api20201101/route_tables_route_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (route *RouteTablesRoute) defaultAzureName() { // defaultImpl applies the code generated defaults to the RouteTablesRoute resource func (route *RouteTablesRoute) defaultImpl() { route.defaultAzureName() } +var _ configmaps.Exporter = &RouteTablesRoute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (route *RouteTablesRoute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RouteTablesRoute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (route *RouteTablesRoute) SecretDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &RouteTablesRoute{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (route *RouteTablesRoute) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (route *RouteTablesRoute) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){route.validateResourceReferences, route.validateOwnerReference} + return []func() (admission.Warnings, error){route.validateResourceReferences, route.validateOwnerReference, route.validateSecretDestinations, route.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (route *RouteTablesRoute) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return route.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return route.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return route.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (route *RouteTablesRoute) validateConfigMapDestinations() (admission.Warnings, error) { + if route.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(route, nil, route.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (route *RouteTablesRoute) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(route) @@ -244,6 +281,14 @@ func (route *RouteTablesRoute) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (route *RouteTablesRoute) validateSecretDestinations() (admission.Warnings, error) { + if route.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(route, nil, route.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (route *RouteTablesRoute) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*RouteTablesRoute) @@ -341,6 +386,10 @@ type RouteTablesRoute_Spec struct { // NextHopType: The type of Azure hop the packet should be sent to. NextHopType *RouteNextHopType `json:"nextHopType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *RouteTablesRouteOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -427,6 +476,8 @@ func (route *RouteTablesRoute_Spec) PopulateFromARM(owner genruntime.ArbitraryOw } } + // no assignment for property "OperatorSpec" + // Set property "Owner": route.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -508,6 +559,18 @@ func (route *RouteTablesRoute_Spec) AssignProperties_From_RouteTablesRoute_Spec( route.NextHopType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec RouteTablesRouteOperatorSpec + err := operatorSpec.AssignProperties_From_RouteTablesRouteOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_RouteTablesRouteOperatorSpec() to populate field OperatorSpec") + } + route.OperatorSpec = &operatorSpec + } else { + route.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -542,6 +605,18 @@ func (route *RouteTablesRoute_Spec) AssignProperties_To_RouteTablesRoute_Spec(de destination.NextHopType = nil } + // OperatorSpec + if route.OperatorSpec != nil { + var operatorSpec storage.RouteTablesRouteOperatorSpec + err := route.OperatorSpec.AssignProperties_To_RouteTablesRouteOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_RouteTablesRouteOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = route.OriginalVersion() @@ -925,6 +1000,110 @@ var routeNextHopType_STATUS_Values = map[string]RouteNextHopType_STATUS{ "vnetlocal": RouteNextHopType_STATUS_VnetLocal, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteTablesRouteOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_RouteTablesRouteOperatorSpec populates our RouteTablesRouteOperatorSpec from the provided source RouteTablesRouteOperatorSpec +func (operator *RouteTablesRouteOperatorSpec) AssignProperties_From_RouteTablesRouteOperatorSpec(source *storage.RouteTablesRouteOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_RouteTablesRouteOperatorSpec populates the provided destination RouteTablesRouteOperatorSpec from our RouteTablesRouteOperatorSpec +func (operator *RouteTablesRouteOperatorSpec) AssignProperties_To_RouteTablesRouteOperatorSpec(destination *storage.RouteTablesRouteOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&RouteTablesRoute{}, &RouteTablesRouteList{}) } diff --git a/v2/api/network/v1api20201101/route_tables_route_types_gen_test.go b/v2/api/network/v1api20201101/route_tables_route_types_gen_test.go index eec0e02845f..136e40f2cef 100644 --- a/v2/api/network/v1api20201101/route_tables_route_types_gen_test.go +++ b/v2/api/network/v1api20201101/route_tables_route_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForRouteTablesRoute(gens map[string]gopter.Gen) gens["Status"] = RouteTablesRoute_STATUSGenerator() } +func Test_RouteTablesRouteOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from RouteTablesRouteOperatorSpec to RouteTablesRouteOperatorSpec via AssignProperties_To_RouteTablesRouteOperatorSpec & AssignProperties_From_RouteTablesRouteOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForRouteTablesRouteOperatorSpec, RouteTablesRouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForRouteTablesRouteOperatorSpec tests if a specific instance of RouteTablesRouteOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForRouteTablesRouteOperatorSpec(subject RouteTablesRouteOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.RouteTablesRouteOperatorSpec + err := copied.AssignProperties_To_RouteTablesRouteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual RouteTablesRouteOperatorSpec + err = actual.AssignProperties_From_RouteTablesRouteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_RouteTablesRouteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteTablesRouteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteTablesRouteOperatorSpec, RouteTablesRouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteTablesRouteOperatorSpec runs a test to see if a specific instance of RouteTablesRouteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteTablesRouteOperatorSpec(subject RouteTablesRouteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteTablesRouteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteTablesRouteOperatorSpec instances for property testing - lazily instantiated by +// RouteTablesRouteOperatorSpecGenerator() +var routeTablesRouteOperatorSpecGenerator gopter.Gen + +// RouteTablesRouteOperatorSpecGenerator returns a generator of RouteTablesRouteOperatorSpec instances for property testing. +func RouteTablesRouteOperatorSpecGenerator() gopter.Gen { + if routeTablesRouteOperatorSpecGenerator != nil { + return routeTablesRouteOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeTablesRouteOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRouteOperatorSpec{}), generators) + + return routeTablesRouteOperatorSpecGenerator +} + func Test_RouteTablesRoute_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -370,6 +467,9 @@ func RunJSONSerializationTestForRouteTablesRoute_Spec(subject RouteTablesRoute_S var routeTablesRoute_SpecGenerator gopter.Gen // RouteTablesRoute_SpecGenerator returns a generator of RouteTablesRoute_Spec instances for property testing. +// We first initialize routeTablesRoute_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RouteTablesRoute_SpecGenerator() gopter.Gen { if routeTablesRoute_SpecGenerator != nil { return routeTablesRoute_SpecGenerator @@ -379,6 +479,12 @@ func RouteTablesRoute_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(generators) routeTablesRoute_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRoute_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(generators) + AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec(generators) + routeTablesRoute_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRoute_Spec{}), generators) + return routeTablesRoute_SpecGenerator } @@ -394,3 +500,8 @@ func AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(gens map[string]go RouteNextHopType_VirtualNetworkGateway, RouteNextHopType_VnetLocal)) } + +// AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RouteTablesRouteOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20201101/storage/load_balancer_types_gen.go b/v2/api/network/v1api20201101/storage/load_balancer_types_gen.go index 9d9abeded09..353f2d5d62c 100644 --- a/v2/api/network/v1api20201101/storage/load_balancer_types_gen.go +++ b/v2/api/network/v1api20201101/storage/load_balancer_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (balancer *LoadBalancer) SetConditions(conditions conditions.Conditions) { balancer.Status.Conditions = conditions } +var _ configmaps.Exporter = &LoadBalancer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (balancer *LoadBalancer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if balancer.Spec.OperatorSpec == nil { + return nil + } + return balancer.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &LoadBalancer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (balancer *LoadBalancer) SecretDestinationExpressions() []*core.DestinationExpression { + if balancer.Spec.OperatorSpec == nil { + return nil + } + return balancer.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &LoadBalancer{} // AzureName returns the Azure name of the resource @@ -157,6 +180,7 @@ type LoadBalancer_Spec struct { InboundNatRules []InboundNatRule_LoadBalancer_SubResourceEmbedded `json:"inboundNatRules,omitempty"` LoadBalancingRules []LoadBalancingRule `json:"loadBalancingRules,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *LoadBalancerOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` OutboundRules []OutboundRule `json:"outboundRules,omitempty"` @@ -502,6 +526,14 @@ type InboundNatRule_STATUS_LoadBalancer_SubResourceEmbedded struct { Type *string `json:"type,omitempty"` } +// Storage version of v1api20201101.LoadBalancerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type LoadBalancerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.LoadBalancerSku // SKU of a load balancer. type LoadBalancerSku struct { diff --git a/v2/api/network/v1api20201101/storage/load_balancer_types_gen_test.go b/v2/api/network/v1api20201101/storage/load_balancer_types_gen_test.go index d514290391e..785526d0f6f 100644 --- a/v2/api/network/v1api20201101/storage/load_balancer_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/load_balancer_types_gen_test.go @@ -1105,6 +1105,61 @@ func AddRelatedPropertyGeneratorsForLoadBalancerBackendAddress_STATUS(gens map[s gens["VirtualNetwork"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_LoadBalancerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of LoadBalancerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForLoadBalancerOperatorSpec, LoadBalancerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForLoadBalancerOperatorSpec runs a test to see if a specific instance of LoadBalancerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForLoadBalancerOperatorSpec(subject LoadBalancerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual LoadBalancerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of LoadBalancerOperatorSpec instances for property testing - lazily instantiated by +// LoadBalancerOperatorSpecGenerator() +var loadBalancerOperatorSpecGenerator gopter.Gen + +// LoadBalancerOperatorSpecGenerator returns a generator of LoadBalancerOperatorSpec instances for property testing. +func LoadBalancerOperatorSpecGenerator() gopter.Gen { + if loadBalancerOperatorSpecGenerator != nil { + return loadBalancerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + loadBalancerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(LoadBalancerOperatorSpec{}), generators) + + return loadBalancerOperatorSpecGenerator +} + func Test_LoadBalancerSku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1402,6 +1457,7 @@ func AddRelatedPropertyGeneratorsForLoadBalancer_Spec(gens map[string]gopter.Gen gens["InboundNatPools"] = gen.SliceOf(InboundNatPoolGenerator()) gens["InboundNatRules"] = gen.SliceOf(InboundNatRule_LoadBalancer_SubResourceEmbeddedGenerator()) gens["LoadBalancingRules"] = gen.SliceOf(LoadBalancingRuleGenerator()) + gens["OperatorSpec"] = gen.PtrOf(LoadBalancerOperatorSpecGenerator()) gens["OutboundRules"] = gen.SliceOf(OutboundRuleGenerator()) gens["Probes"] = gen.SliceOf(ProbeGenerator()) gens["Sku"] = gen.PtrOf(LoadBalancerSkuGenerator()) diff --git a/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen.go b/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen.go index a1ae614e367..8c37a57ca15 100644 --- a/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen.go +++ b/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20240101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (rule *LoadBalancersInboundNatRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &LoadBalancersInboundNatRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *LoadBalancersInboundNatRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &LoadBalancersInboundNatRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *LoadBalancersInboundNatRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &LoadBalancersInboundNatRule{} // AzureName returns the Azure name of the resource @@ -143,14 +166,15 @@ type LoadBalancersInboundNatRuleList struct { type LoadBalancersInboundNatRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - BackendPort *int `json:"backendPort,omitempty"` - EnableFloatingIP *bool `json:"enableFloatingIP,omitempty"` - EnableTcpReset *bool `json:"enableTcpReset,omitempty"` - FrontendIPConfiguration *SubResource `json:"frontendIPConfiguration,omitempty"` - FrontendPort *int `json:"frontendPort,omitempty"` - IdleTimeoutInMinutes *int `json:"idleTimeoutInMinutes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + BackendPort *int `json:"backendPort,omitempty"` + EnableFloatingIP *bool `json:"enableFloatingIP,omitempty"` + EnableTcpReset *bool `json:"enableTcpReset,omitempty"` + FrontendIPConfiguration *SubResource `json:"frontendIPConfiguration,omitempty"` + FrontendPort *int `json:"frontendPort,omitempty"` + IdleTimeoutInMinutes *int `json:"idleTimeoutInMinutes,omitempty"` + OperatorSpec *LoadBalancersInboundNatRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -220,6 +244,14 @@ func (rule *LoadBalancersInboundNatRule_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20201101.LoadBalancersInboundNatRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type LoadBalancersInboundNatRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.NetworkInterfaceIPConfiguration_STATUS_LoadBalancers_InboundNatRule_SubResourceEmbedded // IPConfiguration in a network interface. type NetworkInterfaceIPConfiguration_STATUS_LoadBalancers_InboundNatRule_SubResourceEmbedded struct { diff --git a/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen_test.go b/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen_test.go index 7b4cfcc882c..c2b476d9619 100644 --- a/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/load_balancers_inbound_nat_rule_types_gen_test.go @@ -80,6 +80,61 @@ func AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule(gens map[string] gens["Status"] = LoadBalancersInboundNatRule_STATUSGenerator() } +func Test_LoadBalancersInboundNatRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of LoadBalancersInboundNatRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec, LoadBalancersInboundNatRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec runs a test to see if a specific instance of LoadBalancersInboundNatRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForLoadBalancersInboundNatRuleOperatorSpec(subject LoadBalancersInboundNatRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual LoadBalancersInboundNatRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of LoadBalancersInboundNatRuleOperatorSpec instances for property testing - lazily instantiated by +// LoadBalancersInboundNatRuleOperatorSpecGenerator() +var loadBalancersInboundNatRuleOperatorSpecGenerator gopter.Gen + +// LoadBalancersInboundNatRuleOperatorSpecGenerator returns a generator of LoadBalancersInboundNatRuleOperatorSpec instances for property testing. +func LoadBalancersInboundNatRuleOperatorSpecGenerator() gopter.Gen { + if loadBalancersInboundNatRuleOperatorSpecGenerator != nil { + return loadBalancersInboundNatRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + loadBalancersInboundNatRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(LoadBalancersInboundNatRuleOperatorSpec{}), generators) + + return loadBalancersInboundNatRuleOperatorSpecGenerator +} + func Test_LoadBalancersInboundNatRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -246,6 +301,7 @@ func AddIndependentPropertyGeneratorsForLoadBalancersInboundNatRule_Spec(gens ma // AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForLoadBalancersInboundNatRule_Spec(gens map[string]gopter.Gen) { gens["FrontendIPConfiguration"] = gen.PtrOf(SubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(LoadBalancersInboundNatRuleOperatorSpecGenerator()) } func Test_NetworkInterfaceIPConfiguration_STATUS_LoadBalancers_InboundNatRule_SubResourceEmbedded_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/network/v1api20201101/storage/network_interface_types_gen.go b/v2/api/network/v1api20201101/storage/network_interface_types_gen.go index 15a295ea888..fefa87ddc94 100644 --- a/v2/api/network/v1api20201101/storage/network_interface_types_gen.go +++ b/v2/api/network/v1api20201101/storage/network_interface_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (networkInterface *NetworkInterface) SetConditions(conditions conditions.Co networkInterface.Status.Conditions = conditions } +var _ configmaps.Exporter = &NetworkInterface{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (networkInterface *NetworkInterface) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if networkInterface.Spec.OperatorSpec == nil { + return nil + } + return networkInterface.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkInterface{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (networkInterface *NetworkInterface) SecretDestinationExpressions() []*core.DestinationExpression { + if networkInterface.Spec.OperatorSpec == nil { + return nil + } + return networkInterface.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NetworkInterface{} // AzureName returns the Azure name of the resource @@ -151,6 +174,7 @@ type NetworkInterface_Spec struct { Location *string `json:"location,omitempty"` NetworkSecurityGroup *NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbedded `json:"networkSecurityGroup,omitempty"` NicType *string `json:"nicType,omitempty"` + OperatorSpec *NetworkInterfaceOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -294,6 +318,14 @@ type NetworkInterfaceIPConfiguration_STATUS_NetworkInterface_SubResourceEmbedded VirtualNetworkTaps []VirtualNetworkTap_STATUS_NetworkInterface_SubResourceEmbedded `json:"virtualNetworkTaps,omitempty"` } +// Storage version of v1api20201101.NetworkInterfaceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkInterfaceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded // Tap configuration in a Network Interface. type NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded struct { diff --git a/v2/api/network/v1api20201101/storage/network_interface_types_gen_test.go b/v2/api/network/v1api20201101/storage/network_interface_types_gen_test.go index c08511a5802..c579f8fdb1b 100644 --- a/v2/api/network/v1api20201101/storage/network_interface_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/network_interface_types_gen_test.go @@ -908,6 +908,61 @@ func AddRelatedPropertyGeneratorsForNetworkInterfaceIPConfiguration_STATUS_Netwo gens["VirtualNetworkTaps"] = gen.SliceOf(VirtualNetworkTap_STATUS_NetworkInterface_SubResourceEmbeddedGenerator()) } +func Test_NetworkInterfaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkInterfaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkInterfaceOperatorSpec, NetworkInterfaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkInterfaceOperatorSpec runs a test to see if a specific instance of NetworkInterfaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkInterfaceOperatorSpec(subject NetworkInterfaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkInterfaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkInterfaceOperatorSpec instances for property testing - lazily instantiated by +// NetworkInterfaceOperatorSpecGenerator() +var networkInterfaceOperatorSpecGenerator gopter.Gen + +// NetworkInterfaceOperatorSpecGenerator returns a generator of NetworkInterfaceOperatorSpec instances for property testing. +func NetworkInterfaceOperatorSpecGenerator() gopter.Gen { + if networkInterfaceOperatorSpecGenerator != nil { + return networkInterfaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkInterfaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkInterfaceOperatorSpec{}), generators) + + return networkInterfaceOperatorSpecGenerator +} + func Test_NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1152,6 +1207,7 @@ func AddRelatedPropertyGeneratorsForNetworkInterface_Spec(gens map[string]gopter gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpConfigurations"] = gen.SliceOf(NetworkInterfaceIPConfiguration_NetworkInterface_SubResourceEmbeddedGenerator()) gens["NetworkSecurityGroup"] = gen.PtrOf(NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NetworkInterfaceOperatorSpecGenerator()) gens["PrivateLinkService"] = gen.PtrOf(PrivateLinkServiceSpecGenerator()) } diff --git a/v2/api/network/v1api20201101/storage/network_security_group_types_gen.go b/v2/api/network/v1api20201101/storage/network_security_group_types_gen.go index 201f6533805..386f09b963f 100644 --- a/v2/api/network/v1api20201101/storage/network_security_group_types_gen.go +++ b/v2/api/network/v1api20201101/storage/network_security_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *NetworkSecurityGroup) SetConditions(conditions conditions.Condition group.Status.Conditions = conditions } +var _ configmaps.Exporter = &NetworkSecurityGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *NetworkSecurityGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkSecurityGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *NetworkSecurityGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NetworkSecurityGroup{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type NetworkSecurityGroupList struct { type NetworkSecurityGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *NetworkSecurityGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -228,6 +252,14 @@ type NetworkInterface_STATUS_NetworkSecurityGroup_SubResourceEmbedded struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20201101.NetworkSecurityGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkSecurityGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.SecurityRule_STATUS // Network security rule. type SecurityRule_STATUS struct { diff --git a/v2/api/network/v1api20201101/storage/network_security_group_types_gen_test.go b/v2/api/network/v1api20201101/storage/network_security_group_types_gen_test.go index 43c53e51c40..94d4db5c77e 100644 --- a/v2/api/network/v1api20201101/storage/network_security_group_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/network_security_group_types_gen_test.go @@ -200,6 +200,61 @@ func AddRelatedPropertyGeneratorsForNetworkSecurityGroup(gens map[string]gopter. gens["Status"] = NetworkSecurityGroup_STATUS_NetworkSecurityGroup_SubResourceEmbeddedGenerator() } +func Test_NetworkSecurityGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkSecurityGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec, NetworkSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec runs a test to see if a specific instance of NetworkSecurityGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkSecurityGroupOperatorSpec(subject NetworkSecurityGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkSecurityGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkSecurityGroupOperatorSpec instances for property testing - lazily instantiated by +// NetworkSecurityGroupOperatorSpecGenerator() +var networkSecurityGroupOperatorSpecGenerator gopter.Gen + +// NetworkSecurityGroupOperatorSpecGenerator returns a generator of NetworkSecurityGroupOperatorSpec instances for property testing. +func NetworkSecurityGroupOperatorSpecGenerator() gopter.Gen { + if networkSecurityGroupOperatorSpecGenerator != nil { + return networkSecurityGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkSecurityGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroupOperatorSpec{}), generators) + + return networkSecurityGroupOperatorSpecGenerator +} + func Test_NetworkSecurityGroup_STATUS_NetworkSecurityGroup_SubResourceEmbedded_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -331,6 +386,9 @@ func RunJSONSerializationTestForNetworkSecurityGroup_Spec(subject NetworkSecurit var networkSecurityGroup_SpecGenerator gopter.Gen // NetworkSecurityGroup_SpecGenerator returns a generator of NetworkSecurityGroup_Spec instances for property testing. +// We first initialize networkSecurityGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NetworkSecurityGroup_SpecGenerator() gopter.Gen { if networkSecurityGroup_SpecGenerator != nil { return networkSecurityGroup_SpecGenerator @@ -340,6 +398,12 @@ func NetworkSecurityGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) networkSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) + AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec(generators) + networkSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroup_Spec{}), generators) + return networkSecurityGroup_SpecGenerator } @@ -353,6 +417,11 @@ func AddIndependentPropertyGeneratorsForNetworkSecurityGroup_Spec(gens map[strin gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNetworkSecurityGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NetworkSecurityGroupOperatorSpecGenerator()) +} + func Test_SecurityRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen.go b/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen.go index bb4bb212a09..ced003b4a6c 100644 --- a/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen.go +++ b/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *NetworkSecurityGroupsSecurityRule) SetConditions(conditions conditio rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &NetworkSecurityGroupsSecurityRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NetworkSecurityGroupsSecurityRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NetworkSecurityGroupsSecurityRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NetworkSecurityGroupsSecurityRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NetworkSecurityGroupsSecurityRule{} // AzureName returns the Azure name of the resource @@ -152,6 +175,7 @@ type NetworkSecurityGroupsSecurityRule_Spec struct { DestinationPortRange *string `json:"destinationPortRange,omitempty"` DestinationPortRanges []string `json:"destinationPortRanges,omitempty"` Direction *string `json:"direction,omitempty"` + OperatorSpec *NetworkSecurityGroupsSecurityRuleOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -251,6 +275,14 @@ type ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_SubResource Reference *genruntime.ResourceReference `armReference:"Id" json:"reference,omitempty"` } +// Storage version of v1api20201101.NetworkSecurityGroupsSecurityRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NetworkSecurityGroupsSecurityRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&NetworkSecurityGroupsSecurityRule{}, &NetworkSecurityGroupsSecurityRuleList{}) } diff --git a/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen_test.go b/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen_test.go index 697ba24dc04..b1704751bcc 100644 --- a/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/network_security_groups_security_rule_types_gen_test.go @@ -197,6 +197,61 @@ func AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule(gens map[s gens["Status"] = NetworkSecurityGroupsSecurityRule_STATUSGenerator() } +func Test_NetworkSecurityGroupsSecurityRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NetworkSecurityGroupsSecurityRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec, NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec runs a test to see if a specific instance of NetworkSecurityGroupsSecurityRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNetworkSecurityGroupsSecurityRuleOperatorSpec(subject NetworkSecurityGroupsSecurityRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NetworkSecurityGroupsSecurityRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NetworkSecurityGroupsSecurityRuleOperatorSpec instances for property testing - lazily instantiated by +// NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator() +var networkSecurityGroupsSecurityRuleOperatorSpecGenerator gopter.Gen + +// NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator returns a generator of NetworkSecurityGroupsSecurityRuleOperatorSpec instances for property testing. +func NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator() gopter.Gen { + if networkSecurityGroupsSecurityRuleOperatorSpecGenerator != nil { + return networkSecurityGroupsSecurityRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + networkSecurityGroupsSecurityRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NetworkSecurityGroupsSecurityRuleOperatorSpec{}), generators) + + return networkSecurityGroupsSecurityRuleOperatorSpecGenerator +} + func Test_NetworkSecurityGroupsSecurityRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -377,5 +432,6 @@ func AddIndependentPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec(g // AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNetworkSecurityGroupsSecurityRule_Spec(gens map[string]gopter.Gen) { gens["DestinationApplicationSecurityGroups"] = gen.SliceOf(ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NetworkSecurityGroupsSecurityRuleOperatorSpecGenerator()) gens["SourceApplicationSecurityGroups"] = gen.SliceOf(ApplicationSecurityGroupSpec_NetworkSecurityGroups_SecurityRule_SubResourceEmbeddedGenerator()) } diff --git a/v2/api/network/v1api20201101/storage/public_ip_address_types_gen.go b/v2/api/network/v1api20201101/storage/public_ip_address_types_gen.go index d34addc5cd4..774c25f1d48 100644 --- a/v2/api/network/v1api20201101/storage/public_ip_address_types_gen.go +++ b/v2/api/network/v1api20201101/storage/public_ip_address_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,6 +48,26 @@ func (address *PublicIPAddress) SetConditions(conditions conditions.Conditions) address.Status.Conditions = conditions } +var _ configmaps.Exporter = &PublicIPAddress{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (address *PublicIPAddress) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if address.Spec.OperatorSpec == nil { + return nil + } + return address.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PublicIPAddress{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (address *PublicIPAddress) SecretDestinationExpressions() []*core.DestinationExpression { + if address.Spec.OperatorSpec == nil { + return nil + } + return address.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PublicIPAddress{} // AzureName returns the Azure name of the resource @@ -153,6 +176,7 @@ type PublicIPAddress_Spec struct { LinkedPublicIPAddress *PublicIPAddressSpec_PublicIPAddress_SubResourceEmbedded `json:"linkedPublicIPAddress,omitempty"` Location *string `json:"location,omitempty"` NatGateway *NatGatewaySpec_PublicIPAddress_SubResourceEmbedded `json:"natGateway,omitempty"` + OperatorSpec *PublicIPAddressOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -438,6 +462,14 @@ type PublicIPAddressDnsSettings_STATUS struct { ReverseFqdn *string `json:"reverseFqdn,omitempty"` } +// Storage version of v1api20201101.PublicIPAddressOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PublicIPAddressOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.PublicIPAddressSku // SKU of a public IP address. type PublicIPAddressSku struct { diff --git a/v2/api/network/v1api20201101/storage/public_ip_address_types_gen_test.go b/v2/api/network/v1api20201101/storage/public_ip_address_types_gen_test.go index 27c14d535f6..d1252f41700 100644 --- a/v2/api/network/v1api20201101/storage/public_ip_address_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/public_ip_address_types_gen_test.go @@ -739,6 +739,61 @@ func AddIndependentPropertyGeneratorsForPublicIPAddressDnsSettings_STATUS(gens m gens["ReverseFqdn"] = gen.PtrOf(gen.AlphaString()) } +func Test_PublicIPAddressOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PublicIPAddressOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPublicIPAddressOperatorSpec, PublicIPAddressOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPublicIPAddressOperatorSpec runs a test to see if a specific instance of PublicIPAddressOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPublicIPAddressOperatorSpec(subject PublicIPAddressOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PublicIPAddressOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PublicIPAddressOperatorSpec instances for property testing - lazily instantiated by +// PublicIPAddressOperatorSpecGenerator() +var publicIPAddressOperatorSpecGenerator gopter.Gen + +// PublicIPAddressOperatorSpecGenerator returns a generator of PublicIPAddressOperatorSpec instances for property testing. +func PublicIPAddressOperatorSpecGenerator() gopter.Gen { + if publicIPAddressOperatorSpecGenerator != nil { + return publicIPAddressOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + publicIPAddressOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PublicIPAddressOperatorSpec{}), generators) + + return publicIPAddressOperatorSpecGenerator +} + func Test_PublicIPAddressSku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1102,6 +1157,7 @@ func AddRelatedPropertyGeneratorsForPublicIPAddress_Spec(gens map[string]gopter. gens["IpTags"] = gen.SliceOf(IpTagGenerator()) gens["LinkedPublicIPAddress"] = gen.PtrOf(PublicIPAddressSpec_PublicIPAddress_SubResourceEmbeddedGenerator()) gens["NatGateway"] = gen.PtrOf(NatGatewaySpec_PublicIPAddress_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PublicIPAddressOperatorSpecGenerator()) gens["PublicIPPrefix"] = gen.PtrOf(SubResourceGenerator()) gens["ServicePublicIPAddress"] = gen.PtrOf(PublicIPAddressSpec_PublicIPAddress_SubResourceEmbeddedGenerator()) gens["Sku"] = gen.PtrOf(PublicIPAddressSkuGenerator()) diff --git a/v2/api/network/v1api20201101/storage/route_table_types_gen.go b/v2/api/network/v1api20201101/storage/route_table_types_gen.go index 24d53663040..e13ebf84252 100644 --- a/v2/api/network/v1api20201101/storage/route_table_types_gen.go +++ b/v2/api/network/v1api20201101/storage/route_table_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (table *RouteTable) SetConditions(conditions conditions.Conditions) { table.Status.Conditions = conditions } +var _ configmaps.Exporter = &RouteTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *RouteTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RouteTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *RouteTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RouteTable{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type RouteTableList struct { type RouteTable_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DisableBgpRoutePropagation *bool `json:"disableBgpRoutePropagation,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DisableBgpRoutePropagation *bool `json:"disableBgpRoutePropagation,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *RouteTableOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -212,6 +236,14 @@ func (table *RouteTable_STATUS) ConvertStatusTo(destination genruntime.Convertib return destination.ConvertStatusFrom(table) } +// Storage version of v1api20201101.RouteTableOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteTableOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&RouteTable{}, &RouteTableList{}) } diff --git a/v2/api/network/v1api20201101/storage/route_table_types_gen_test.go b/v2/api/network/v1api20201101/storage/route_table_types_gen_test.go index 61e10231d61..a7bdbce1bcc 100644 --- a/v2/api/network/v1api20201101/storage/route_table_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/route_table_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRouteTable(gens map[string]gopter.Gen) { gens["Status"] = RouteTable_STATUSGenerator() } +func Test_RouteTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteTableOperatorSpec, RouteTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteTableOperatorSpec runs a test to see if a specific instance of RouteTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteTableOperatorSpec(subject RouteTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteTableOperatorSpec instances for property testing - lazily instantiated by +// RouteTableOperatorSpecGenerator() +var routeTableOperatorSpecGenerator gopter.Gen + +// RouteTableOperatorSpecGenerator returns a generator of RouteTableOperatorSpec instances for property testing. +func RouteTableOperatorSpecGenerator() gopter.Gen { + if routeTableOperatorSpecGenerator != nil { + return routeTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteTableOperatorSpec{}), generators) + + return routeTableOperatorSpecGenerator +} + func Test_RouteTable_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -191,6 +246,9 @@ func RunJSONSerializationTestForRouteTable_Spec(subject RouteTable_Spec) string var routeTable_SpecGenerator gopter.Gen // RouteTable_SpecGenerator returns a generator of RouteTable_Spec instances for property testing. +// We first initialize routeTable_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RouteTable_SpecGenerator() gopter.Gen { if routeTable_SpecGenerator != nil { return routeTable_SpecGenerator @@ -200,6 +258,12 @@ func RouteTable_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRouteTable_Spec(generators) routeTable_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTable_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRouteTable_Spec(generators) + AddRelatedPropertyGeneratorsForRouteTable_Spec(generators) + routeTable_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTable_Spec{}), generators) + return routeTable_SpecGenerator } @@ -213,3 +277,8 @@ func AddIndependentPropertyGeneratorsForRouteTable_Spec(gens map[string]gopter.G gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForRouteTable_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRouteTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RouteTableOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20201101/storage/route_tables_route_types_gen.go b/v2/api/network/v1api20201101/storage/route_tables_route_types_gen.go index 4402a8100e6..349ab292fc1 100644 --- a/v2/api/network/v1api20201101/storage/route_tables_route_types_gen.go +++ b/v2/api/network/v1api20201101/storage/route_tables_route_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (route *RouteTablesRoute) SetConditions(conditions conditions.Conditions) { route.Status.Conditions = conditions } +var _ configmaps.Exporter = &RouteTablesRoute{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (route *RouteTablesRoute) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &RouteTablesRoute{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (route *RouteTablesRoute) SecretDestinationExpressions() []*core.DestinationExpression { + if route.Spec.OperatorSpec == nil { + return nil + } + return route.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &RouteTablesRoute{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type RouteTablesRoute_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - NextHopIpAddress *string `json:"nextHopIpAddress,omitempty"` - NextHopType *string `json:"nextHopType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + NextHopIpAddress *string `json:"nextHopIpAddress,omitempty"` + NextHopType *string `json:"nextHopType,omitempty"` + OperatorSpec *RouteTablesRouteOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -212,6 +236,14 @@ func (route *RouteTablesRoute_STATUS) ConvertStatusTo(destination genruntime.Con return destination.ConvertStatusFrom(route) } +// Storage version of v1api20201101.RouteTablesRouteOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type RouteTablesRouteOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&RouteTablesRoute{}, &RouteTablesRouteList{}) } diff --git a/v2/api/network/v1api20201101/storage/route_tables_route_types_gen_test.go b/v2/api/network/v1api20201101/storage/route_tables_route_types_gen_test.go index 84dab6b2f44..a5411d892c9 100644 --- a/v2/api/network/v1api20201101/storage/route_tables_route_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/route_tables_route_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForRouteTablesRoute(gens map[string]gopter.Gen) gens["Status"] = RouteTablesRoute_STATUSGenerator() } +func Test_RouteTablesRouteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of RouteTablesRouteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForRouteTablesRouteOperatorSpec, RouteTablesRouteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForRouteTablesRouteOperatorSpec runs a test to see if a specific instance of RouteTablesRouteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForRouteTablesRouteOperatorSpec(subject RouteTablesRouteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual RouteTablesRouteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of RouteTablesRouteOperatorSpec instances for property testing - lazily instantiated by +// RouteTablesRouteOperatorSpecGenerator() +var routeTablesRouteOperatorSpecGenerator gopter.Gen + +// RouteTablesRouteOperatorSpecGenerator returns a generator of RouteTablesRouteOperatorSpec instances for property testing. +func RouteTablesRouteOperatorSpecGenerator() gopter.Gen { + if routeTablesRouteOperatorSpecGenerator != nil { + return routeTablesRouteOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + routeTablesRouteOperatorSpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRouteOperatorSpec{}), generators) + + return routeTablesRouteOperatorSpecGenerator +} + func Test_RouteTablesRoute_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -191,6 +246,9 @@ func RunJSONSerializationTestForRouteTablesRoute_Spec(subject RouteTablesRoute_S var routeTablesRoute_SpecGenerator gopter.Gen // RouteTablesRoute_SpecGenerator returns a generator of RouteTablesRoute_Spec instances for property testing. +// We first initialize routeTablesRoute_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func RouteTablesRoute_SpecGenerator() gopter.Gen { if routeTablesRoute_SpecGenerator != nil { return routeTablesRoute_SpecGenerator @@ -200,6 +258,12 @@ func RouteTablesRoute_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(generators) routeTablesRoute_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRoute_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(generators) + AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec(generators) + routeTablesRoute_SpecGenerator = gen.Struct(reflect.TypeOf(RouteTablesRoute_Spec{}), generators) + return routeTablesRoute_SpecGenerator } @@ -211,3 +275,8 @@ func AddIndependentPropertyGeneratorsForRouteTablesRoute_Spec(gens map[string]go gens["NextHopType"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForRouteTablesRoute_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(RouteTablesRouteOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20201101/storage/structure.txt b/v2/api/network/v1api20201101/storage/structure.txt index 2e6c6069ca4..0ce5420b8b8 100644 --- a/v2/api/network/v1api20201101/storage/structure.txt +++ b/v2/api/network/v1api20201101/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-11-01" LoadBalancer: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AzureName: string │ ├── BackendAddressPools: Object (3 properties)[] │ │ ├── LoadBalancerBackendAddresses: Object (6 properties)[] @@ -89,6 +89,10 @@ LoadBalancer: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Protocol: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── OutboundRules: Object (8 properties)[] │ │ ├── AllocatedOutboundPorts: *int @@ -298,7 +302,7 @@ LoadBalancer: Resource └── Type: *string LoadBalancersInboundNatRule: Resource ├── Owner: network/v1api20201101.LoadBalancer -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── BackendPort: *int │ ├── EnableFloatingIP: *bool @@ -308,6 +312,10 @@ LoadBalancersInboundNatRule: Resource │ │ └── Reference: *genruntime.ResourceReference │ ├── FrontendPort: *int │ ├── IdleTimeoutInMinutes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -334,7 +342,7 @@ LoadBalancersInboundNatRule: Resource └── Type: *string NetworkInterface: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AzureName: string │ ├── DnsSettings: *Object (3 properties) │ │ ├── DnsServers: string[] @@ -379,6 +387,10 @@ NetworkInterface: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── NicType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkService: *Object (2 properties) @@ -472,9 +484,13 @@ NetworkInterface: Resource └── PropertyBag: genruntime.PropertyBag NetworkSecurityGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -504,7 +520,7 @@ NetworkSecurityGroup: Resource └── Type: *string NetworkSecurityGroupsSecurityRule: Resource ├── Owner: network/v1api20201101.NetworkSecurityGroup -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── Access: *string │ ├── AzureName: string │ ├── Description: *string @@ -516,6 +532,10 @@ NetworkSecurityGroupsSecurityRule: Resource │ ├── DestinationPortRange: *string │ ├── DestinationPortRanges: string[] │ ├── Direction: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int @@ -557,7 +577,7 @@ NetworkSecurityGroupsSecurityRule: Resource └── Type: *string PublicIPAddress: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (20 properties) +├── Spec: Object (21 properties) │ ├── AzureName: string │ ├── DdosSettings: *Object (4 properties) │ │ ├── DdosCustomPolicy: *Object (2 properties) @@ -588,6 +608,10 @@ PublicIPAddress: Resource │ ├── NatGateway: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -657,10 +681,14 @@ PublicIPAddress: Resource └── Zones: string[] RouteTable: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── DisableBgpRoutePropagation: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -679,11 +707,15 @@ RouteTable: Resource └── Type: *string RouteTablesRoute: Resource ├── Owner: network/v1api20201101.RouteTable -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AddressPrefix: *string │ ├── AzureName: string │ ├── NextHopIpAddress: *string │ ├── NextHopType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -701,7 +733,7 @@ RouteTablesRoute: Resource └── Type: *string VirtualNetwork: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AddressSpace: *Object (2 properties) │ │ ├── AddressPrefixes: string[] │ │ └── PropertyBag: genruntime.PropertyBag @@ -725,6 +757,10 @@ VirtualNetwork: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -764,7 +800,7 @@ VirtualNetwork: Resource └── Type: *string VirtualNetworkGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (21 properties) +├── Spec: Object (22 properties) │ ├── ActiveActive: *bool │ ├── AzureName: string │ ├── BgpSettings: *Object (5 properties) @@ -801,6 +837,10 @@ VirtualNetworkGateway: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -950,7 +990,7 @@ VirtualNetworkGateway: Resource └── VpnType: *string VirtualNetworksSubnet: Resource ├── Owner: network/v1api20201101.VirtualNetwork -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AddressPrefix: *string │ ├── AddressPrefixes: string[] │ ├── ApplicationGatewayIpConfigurations: Object (2 properties)[] @@ -970,6 +1010,10 @@ VirtualNetworksSubnet: Resource │ ├── NetworkSecurityGroup: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateEndpointNetworkPolicies: *string @@ -1047,12 +1091,16 @@ VirtualNetworksSubnet: Resource └── Type: *string VirtualNetworksVirtualNetworkPeering: Resource ├── Owner: network/v1api20201101.VirtualNetwork -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AllowForwardedTraffic: *bool │ ├── AllowGatewayTransit: *bool │ ├── AllowVirtualNetworkAccess: *bool │ ├── AzureName: string │ ├── DoNotVerifyRemoteGateways: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PeeringState: *string diff --git a/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen.go b/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen.go index 28948d36320..04770a2a602 100644 --- a/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen.go +++ b/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (gateway *VirtualNetworkGateway) SetConditions(conditions conditions.Condit gateway.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualNetworkGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *VirtualNetworkGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworkGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *VirtualNetworkGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualNetworkGateway{} // AzureName returns the Azure name of the resource @@ -155,6 +178,7 @@ type VirtualNetworkGateway_Spec struct { GatewayType *string `json:"gatewayType,omitempty"` IpConfigurations []VirtualNetworkGatewayIPConfiguration `json:"ipConfigurations,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *VirtualNetworkGatewayOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -289,6 +313,14 @@ type VirtualNetworkGatewayIPConfiguration_STATUS struct { Subnet *SubResource_STATUS `json:"subnet,omitempty"` } +// Storage version of v1api20201101.VirtualNetworkGatewayOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworkGatewayOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20201101.VirtualNetworkGatewaySku // VirtualNetworkGatewaySku details. type VirtualNetworkGatewaySku struct { diff --git a/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen_test.go b/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen_test.go index b9e3e56489b..7b4eff62419 100644 --- a/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/virtual_network_gateway_types_gen_test.go @@ -774,6 +774,61 @@ func AddRelatedPropertyGeneratorsForVirtualNetworkGatewayIPConfiguration_STATUS( gens["Subnet"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_VirtualNetworkGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworkGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec, VirtualNetworkGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec runs a test to see if a specific instance of VirtualNetworkGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec(subject VirtualNetworkGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworkGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworkGatewayOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworkGatewayOperatorSpecGenerator() +var virtualNetworkGatewayOperatorSpecGenerator gopter.Gen + +// VirtualNetworkGatewayOperatorSpecGenerator returns a generator of VirtualNetworkGatewayOperatorSpec instances for property testing. +func VirtualNetworkGatewayOperatorSpecGenerator() gopter.Gen { + if virtualNetworkGatewayOperatorSpecGenerator != nil { + return virtualNetworkGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworkGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworkGatewayOperatorSpec{}), generators) + + return virtualNetworkGatewayOperatorSpecGenerator +} + func Test_VirtualNetworkGatewaySku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1087,6 +1142,7 @@ func AddRelatedPropertyGeneratorsForVirtualNetworkGateway_Spec(gens map[string]g gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["GatewayDefaultSite"] = gen.PtrOf(SubResourceGenerator()) gens["IpConfigurations"] = gen.SliceOf(VirtualNetworkGatewayIPConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworkGatewayOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(VirtualNetworkGatewaySkuGenerator()) gens["VpnClientConfiguration"] = gen.PtrOf(VpnClientConfigurationGenerator()) } diff --git a/v2/api/network/v1api20201101/storage/virtual_network_types_gen.go b/v2/api/network/v1api20201101/storage/virtual_network_types_gen.go index 4d68d3bd331..134a24cb7a5 100644 --- a/v2/api/network/v1api20201101/storage/virtual_network_types_gen.go +++ b/v2/api/network/v1api20201101/storage/virtual_network_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (network *VirtualNetwork) SetConditions(conditions conditions.Conditions) { network.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualNetwork{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (network *VirtualNetwork) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if network.Spec.OperatorSpec == nil { + return nil + } + return network.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetwork{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (network *VirtualNetwork) SecretDestinationExpressions() []*core.DestinationExpression { + if network.Spec.OperatorSpec == nil { + return nil + } + return network.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualNetwork{} // AzureName returns the Azure name of the resource @@ -153,6 +176,7 @@ type VirtualNetwork_Spec struct { ExtendedLocation *ExtendedLocation `json:"extendedLocation,omitempty"` IpAllocations []SubResource `json:"ipAllocations,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *VirtualNetworkOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -272,6 +296,14 @@ type VirtualNetworkBgpCommunities_STATUS struct { VirtualNetworkCommunity *string `json:"virtualNetworkCommunity,omitempty"` } +// Storage version of v1api20201101.VirtualNetworkOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworkOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&VirtualNetwork{}, &VirtualNetworkList{}) } diff --git a/v2/api/network/v1api20201101/storage/virtual_network_types_gen_test.go b/v2/api/network/v1api20201101/storage/virtual_network_types_gen_test.go index f3c426d0a4b..e397d1cbed3 100644 --- a/v2/api/network/v1api20201101/storage/virtual_network_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/virtual_network_types_gen_test.go @@ -442,6 +442,61 @@ func AddIndependentPropertyGeneratorsForVirtualNetworkBgpCommunities_STATUS(gens gens["VirtualNetworkCommunity"] = gen.PtrOf(gen.AlphaString()) } +func Test_VirtualNetworkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworkOperatorSpec, VirtualNetworkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworkOperatorSpec runs a test to see if a specific instance of VirtualNetworkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworkOperatorSpec(subject VirtualNetworkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworkOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworkOperatorSpecGenerator() +var virtualNetworkOperatorSpecGenerator gopter.Gen + +// VirtualNetworkOperatorSpecGenerator returns a generator of VirtualNetworkOperatorSpec instances for property testing. +func VirtualNetworkOperatorSpecGenerator() gopter.Gen { + if virtualNetworkOperatorSpecGenerator != nil { + return virtualNetworkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworkOperatorSpec{}), generators) + + return virtualNetworkOperatorSpecGenerator +} + func Test_VirtualNetwork_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -618,4 +673,5 @@ func AddRelatedPropertyGeneratorsForVirtualNetwork_Spec(gens map[string]gopter.G gens["DhcpOptions"] = gen.PtrOf(DhcpOptionsGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpAllocations"] = gen.SliceOf(SubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworkOperatorSpecGenerator()) } diff --git a/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen.go b/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen.go index b4f1bf4c17f..5a52bbb6a14 100644 --- a/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen.go +++ b/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (subnet *VirtualNetworksSubnet) SetConditions(conditions conditions.Conditi subnet.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualNetworksSubnet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subnet *VirtualNetworksSubnet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subnet.Spec.OperatorSpec == nil { + return nil + } + return subnet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworksSubnet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subnet *VirtualNetworksSubnet) SecretDestinationExpressions() []*core.DestinationExpression { + if subnet.Spec.OperatorSpec == nil { + return nil + } + return subnet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualNetworksSubnet{} // AzureName returns the Azure name of the resource @@ -151,6 +174,7 @@ type VirtualNetworksSubnet_Spec struct { IpAllocations []SubResource `json:"ipAllocations,omitempty"` NatGateway *SubResource `json:"natGateway,omitempty"` NetworkSecurityGroup *NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbedded `json:"networkSecurityGroup,omitempty"` + OperatorSpec *VirtualNetworksSubnetOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -372,6 +396,14 @@ type ServiceEndpointPropertiesFormat_STATUS struct { Service *string `json:"service,omitempty"` } +// Storage version of v1api20201101.VirtualNetworksSubnetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworksSubnetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&VirtualNetworksSubnet{}, &VirtualNetworksSubnetList{}) } diff --git a/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen_test.go b/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen_test.go index a81ecaf3649..44bc075dbc5 100644 --- a/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/virtual_networks_subnet_types_gen_test.go @@ -1101,6 +1101,61 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksSubnet(gens map[string]gopter gens["Status"] = VirtualNetworksSubnet_STATUSGenerator() } +func Test_VirtualNetworksSubnetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworksSubnetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec, VirtualNetworksSubnetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec runs a test to see if a specific instance of VirtualNetworksSubnetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec(subject VirtualNetworksSubnetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworksSubnetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworksSubnetOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworksSubnetOperatorSpecGenerator() +var virtualNetworksSubnetOperatorSpecGenerator gopter.Gen + +// VirtualNetworksSubnetOperatorSpecGenerator returns a generator of VirtualNetworksSubnetOperatorSpec instances for property testing. +func VirtualNetworksSubnetOperatorSpecGenerator() gopter.Gen { + if virtualNetworksSubnetOperatorSpecGenerator != nil { + return virtualNetworksSubnetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworksSubnetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworksSubnetOperatorSpec{}), generators) + + return virtualNetworksSubnetOperatorSpecGenerator +} + func Test_VirtualNetworksSubnet_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1279,6 +1334,7 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksSubnet_Spec(gens map[string]g gens["IpAllocations"] = gen.SliceOf(SubResourceGenerator()) gens["NatGateway"] = gen.PtrOf(SubResourceGenerator()) gens["NetworkSecurityGroup"] = gen.PtrOf(NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworksSubnetOperatorSpecGenerator()) gens["RouteTable"] = gen.PtrOf(RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) gens["ServiceEndpointPolicies"] = gen.SliceOf(ServiceEndpointPolicySpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) gens["ServiceEndpoints"] = gen.SliceOf(ServiceEndpointPropertiesFormatGenerator()) diff --git a/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen.go b/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen.go index 52c747ac677..bc0ab8564ab 100644 --- a/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen.go +++ b/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (peering *VirtualNetworksVirtualNetworkPeering) SetConditions(conditions co peering.Status.Conditions = conditions } +var _ configmaps.Exporter = &VirtualNetworksVirtualNetworkPeering{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (peering *VirtualNetworksVirtualNetworkPeering) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if peering.Spec.OperatorSpec == nil { + return nil + } + return peering.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworksVirtualNetworkPeering{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (peering *VirtualNetworksVirtualNetworkPeering) SecretDestinationExpressions() []*core.DestinationExpression { + if peering.Spec.OperatorSpec == nil { + return nil + } + return peering.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &VirtualNetworksVirtualNetworkPeering{} // AzureName returns the Azure name of the resource @@ -146,9 +169,10 @@ type VirtualNetworksVirtualNetworkPeering_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DoNotVerifyRemoteGateways *bool `json:"doNotVerifyRemoteGateways,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DoNotVerifyRemoteGateways *bool `json:"doNotVerifyRemoteGateways,omitempty"` + OperatorSpec *VirtualNetworksVirtualNetworkPeeringOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -224,6 +248,14 @@ func (peering *VirtualNetworksVirtualNetworkPeering_STATUS) ConvertStatusTo(dest return destination.ConvertStatusFrom(peering) } +// Storage version of v1api20201101.VirtualNetworksVirtualNetworkPeeringOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworksVirtualNetworkPeeringOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&VirtualNetworksVirtualNetworkPeering{}, &VirtualNetworksVirtualNetworkPeeringList{}) } diff --git a/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen_test.go b/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen_test.go index 1d0925fe28d..752a24a49ea 100644 --- a/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen_test.go +++ b/v2/api/network/v1api20201101/storage/virtual_networks_virtual_network_peering_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering(gens ma gens["Status"] = VirtualNetworksVirtualNetworkPeering_STATUSGenerator() } +func Test_VirtualNetworksVirtualNetworkPeeringOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworksVirtualNetworkPeeringOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec, VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec runs a test to see if a specific instance of VirtualNetworksVirtualNetworkPeeringOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec(subject VirtualNetworksVirtualNetworkPeeringOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworksVirtualNetworkPeeringOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworksVirtualNetworkPeeringOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator() +var virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator gopter.Gen + +// VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator returns a generator of VirtualNetworksVirtualNetworkPeeringOperatorSpec instances for property testing. +func VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator() gopter.Gen { + if virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator != nil { + return virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworksVirtualNetworkPeeringOperatorSpec{}), generators) + + return virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator +} + func Test_VirtualNetworksVirtualNetworkPeering_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -246,6 +301,7 @@ func AddIndependentPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spe // AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator()) gens["RemoteAddressSpace"] = gen.PtrOf(AddressSpaceGenerator()) gens["RemoteBgpCommunities"] = gen.PtrOf(VirtualNetworkBgpCommunitiesGenerator()) gens["RemoteVirtualNetwork"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/network/v1api20201101/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20201101/storage/zz_generated.deepcopy.go index 36368f65795..a867aaa5855 100644 --- a/v2/api/network/v1api20201101/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20201101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1879,6 +1880,50 @@ func (in *LoadBalancerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancerOperatorSpec) DeepCopyInto(out *LoadBalancerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerOperatorSpec. +func (in *LoadBalancerOperatorSpec) DeepCopy() *LoadBalancerOperatorSpec { + if in == nil { + return nil + } + out := new(LoadBalancerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerSku) DeepCopyInto(out *LoadBalancerSku) { *out = *in @@ -2121,6 +2166,11 @@ func (in *LoadBalancer_Spec) DeepCopyInto(out *LoadBalancer_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(LoadBalancerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OutboundRules != nil { in, out := &in.OutboundRules, &out.OutboundRules *out = make([]OutboundRule, len(*in)) @@ -2230,6 +2280,50 @@ func (in *LoadBalancersInboundNatRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancersInboundNatRuleOperatorSpec) DeepCopyInto(out *LoadBalancersInboundNatRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancersInboundNatRuleOperatorSpec. +func (in *LoadBalancersInboundNatRuleOperatorSpec) DeepCopy() *LoadBalancersInboundNatRuleOperatorSpec { + if in == nil { + return nil + } + out := new(LoadBalancersInboundNatRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancersInboundNatRule_STATUS) DeepCopyInto(out *LoadBalancersInboundNatRule_STATUS) { *out = *in @@ -2357,6 +2451,11 @@ func (in *LoadBalancersInboundNatRule_Spec) DeepCopyInto(out *LoadBalancersInbou *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(LoadBalancersInboundNatRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3062,6 +3161,50 @@ func (in *NetworkInterfaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInterfaceOperatorSpec) DeepCopyInto(out *NetworkInterfaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInterfaceOperatorSpec. +func (in *NetworkInterfaceOperatorSpec) DeepCopy() *NetworkInterfaceOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkInterfaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -3316,6 +3459,11 @@ func (in *NetworkInterface_Spec) DeepCopyInto(out *NetworkInterface_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkInterfaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3411,6 +3559,50 @@ func (in *NetworkSecurityGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSecurityGroupOperatorSpec) DeepCopyInto(out *NetworkSecurityGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSecurityGroupOperatorSpec. +func (in *NetworkSecurityGroupOperatorSpec) DeepCopy() *NetworkSecurityGroupOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkSecurityGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -3626,6 +3818,11 @@ func (in *NetworkSecurityGroup_Spec) DeepCopyInto(out *NetworkSecurityGroup_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkSecurityGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3716,6 +3913,50 @@ func (in *NetworkSecurityGroupsSecurityRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSecurityGroupsSecurityRuleOperatorSpec) DeepCopyInto(out *NetworkSecurityGroupsSecurityRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSecurityGroupsSecurityRuleOperatorSpec. +func (in *NetworkSecurityGroupsSecurityRuleOperatorSpec) DeepCopy() *NetworkSecurityGroupsSecurityRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkSecurityGroupsSecurityRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkSecurityGroupsSecurityRule_STATUS) DeepCopyInto(out *NetworkSecurityGroupsSecurityRule_STATUS) { *out = *in @@ -3894,6 +4135,11 @@ func (in *NetworkSecurityGroupsSecurityRule_Spec) DeepCopyInto(out *NetworkSecur *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkSecurityGroupsSecurityRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4465,6 +4711,50 @@ func (in *PublicIPAddressList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PublicIPAddressOperatorSpec) DeepCopyInto(out *PublicIPAddressOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PublicIPAddressOperatorSpec. +func (in *PublicIPAddressOperatorSpec) DeepCopy() *PublicIPAddressOperatorSpec { + if in == nil { + return nil + } + out := new(PublicIPAddressOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PublicIPAddressSku) DeepCopyInto(out *PublicIPAddressSku) { *out = *in @@ -4857,6 +5147,11 @@ func (in *PublicIPAddress_Spec) DeepCopyInto(out *PublicIPAddress_Spec) { *out = new(NatGatewaySpec_PublicIPAddress_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PublicIPAddressOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5078,6 +5373,50 @@ func (in *RouteTableList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteTableOperatorSpec) DeepCopyInto(out *RouteTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTableOperatorSpec. +func (in *RouteTableOperatorSpec) DeepCopy() *RouteTableOperatorSpec { + if in == nil { + return nil + } + out := new(RouteTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbedded) DeepCopyInto(out *RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbedded) { *out = *in @@ -5221,6 +5560,11 @@ func (in *RouteTable_Spec) DeepCopyInto(out *RouteTable_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5311,6 +5655,50 @@ func (in *RouteTablesRouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteTablesRouteOperatorSpec) DeepCopyInto(out *RouteTablesRouteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTablesRouteOperatorSpec. +func (in *RouteTablesRouteOperatorSpec) DeepCopy() *RouteTablesRouteOperatorSpec { + if in == nil { + return nil + } + out := new(RouteTablesRouteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteTablesRoute_STATUS) DeepCopyInto(out *RouteTablesRoute_STATUS) { *out = *in @@ -5403,6 +5791,11 @@ func (in *RouteTablesRoute_Spec) DeepCopyInto(out *RouteTablesRoute_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteTablesRouteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6042,6 +6435,50 @@ func (in *VirtualNetworkGatewayList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworkGatewayOperatorSpec) DeepCopyInto(out *VirtualNetworkGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworkGatewayOperatorSpec. +func (in *VirtualNetworkGatewayOperatorSpec) DeepCopy() *VirtualNetworkGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworkGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworkGatewaySku) DeepCopyInto(out *VirtualNetworkGatewaySku) { *out = *in @@ -6324,6 +6761,11 @@ func (in *VirtualNetworkGateway_Spec) DeepCopyInto(out *VirtualNetworkGateway_Sp *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworkGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6412,6 +6854,50 @@ func (in *VirtualNetworkList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworkOperatorSpec) DeepCopyInto(out *VirtualNetworkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworkOperatorSpec. +func (in *VirtualNetworkOperatorSpec) DeepCopy() *VirtualNetworkOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworkTapSpec_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *VirtualNetworkTapSpec_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -6629,6 +7115,11 @@ func (in *VirtualNetwork_Spec) DeepCopyInto(out *VirtualNetwork_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6719,6 +7210,50 @@ func (in *VirtualNetworksSubnetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworksSubnetOperatorSpec) DeepCopyInto(out *VirtualNetworksSubnetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworksSubnetOperatorSpec. +func (in *VirtualNetworksSubnetOperatorSpec) DeepCopy() *VirtualNetworksSubnetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworksSubnetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworksSubnet_STATUS) DeepCopyInto(out *VirtualNetworksSubnet_STATUS) { *out = *in @@ -6927,6 +7462,11 @@ func (in *VirtualNetworksSubnet_Spec) DeepCopyInto(out *VirtualNetworksSubnet_Sp *out = new(NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworksSubnetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -7039,6 +7579,50 @@ func (in *VirtualNetworksVirtualNetworkPeeringList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworksVirtualNetworkPeeringOperatorSpec) DeepCopyInto(out *VirtualNetworksVirtualNetworkPeeringOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworksVirtualNetworkPeeringOperatorSpec. +func (in *VirtualNetworksVirtualNetworkPeeringOperatorSpec) DeepCopy() *VirtualNetworksVirtualNetworkPeeringOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworksVirtualNetworkPeeringOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworksVirtualNetworkPeering_STATUS) DeepCopyInto(out *VirtualNetworksVirtualNetworkPeering_STATUS) { *out = *in @@ -7166,6 +7750,11 @@ func (in *VirtualNetworksVirtualNetworkPeering_Spec) DeepCopyInto(out *VirtualNe *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworksVirtualNetworkPeeringOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20201101/structure.txt b/v2/api/network/v1api20201101/structure.txt index 3d26df71337..d32388d2240 100644 --- a/v2/api/network/v1api20201101/structure.txt +++ b/v2/api/network/v1api20201101/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2020-11-01" LoadBalancer: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── BackendAddressPools: Object (2 properties)[] │ │ ├── LoadBalancerBackendAddresses: Object (5 properties)[] @@ -88,6 +88,9 @@ LoadBalancer: Resource │ │ ├── "Tcp" │ │ └── "Udp" │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OutboundRules: Object (7 properties)[] │ │ ├── AllocatedOutboundPorts: *int │ │ ├── BackendAddressPool: *Object (1 property) @@ -324,7 +327,7 @@ LoadBalancer: Resource └── Type: *string LoadBalancersInboundNatRule: Resource ├── Owner: LoadBalancer -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── BackendPort: *int │ ├── EnableFloatingIP: *bool @@ -333,6 +336,9 @@ LoadBalancersInboundNatRule: Resource │ │ └── Reference: *genruntime.ResourceReference │ ├── FrontendPort: *int │ ├── IdleTimeoutInMinutes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Protocol: *Enum (3 values) │ ├── "All" @@ -364,7 +370,7 @@ LoadBalancersInboundNatRule: Resource └── Type: *string NetworkInterface: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AzureName: string │ ├── DnsSettings: *Object (2 properties) │ │ ├── DnsServers: string[] @@ -405,6 +411,9 @@ NetworkInterface: Resource │ ├── NicType: *Enum (2 values) │ │ ├── "Elastic" │ │ └── "Standard" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkService: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -497,9 +506,12 @@ NetworkInterface: Resource └── Id: *string NetworkSecurityGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (13 properties) @@ -526,7 +538,7 @@ NetworkSecurityGroup: Resource └── Type: *string NetworkSecurityGroupsSecurityRule: Resource ├── Owner: NetworkSecurityGroup -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── Access: *Enum (2 values) │ │ ├── "Allow" │ │ └── "Deny" @@ -541,6 +553,9 @@ NetworkSecurityGroupsSecurityRule: Resource │ ├── Direction: *Enum (2 values) │ │ ├── "Inbound" │ │ └── "Outbound" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int │ ├── Protocol: *Enum (6 values) @@ -596,7 +611,7 @@ NetworkSecurityGroupsSecurityRule: Resource └── Type: *string PublicIPAddress: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AzureName: string │ ├── DdosSettings: *Object (3 properties) │ │ ├── DdosCustomPolicy: *Object (1 property) @@ -623,6 +638,9 @@ PublicIPAddress: Resource │ ├── Location: *string │ ├── NatGateway: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicIPAddressVersion: *Enum (2 values) │ │ ├── "IPv4" @@ -705,10 +723,13 @@ PublicIPAddress: Resource └── Zones: string[] RouteTable: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── DisableBgpRoutePropagation: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (10 properties) @@ -728,7 +749,7 @@ RouteTable: Resource └── Type: *string RouteTablesRoute: Resource ├── Owner: RouteTable -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AddressPrefix: *string │ ├── AzureName: string │ ├── NextHopIpAddress: *string @@ -738,6 +759,9 @@ RouteTablesRoute: Resource │ │ ├── "VirtualAppliance" │ │ ├── "VirtualNetworkGateway" │ │ └── "VnetLocal" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (10 properties) ├── AddressPrefix: *string @@ -761,7 +785,7 @@ RouteTablesRoute: Resource └── Type: *string VirtualNetwork: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AddressSpace: *Object (1 property) │ │ └── AddressPrefixes: string[] │ ├── AzureName: string @@ -780,6 +804,9 @@ VirtualNetwork: Resource │ ├── IpAllocations: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (17 properties) @@ -815,7 +842,7 @@ VirtualNetwork: Resource └── Type: *string VirtualNetworkGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── ActiveActive: *bool │ ├── AzureName: string │ ├── BgpSettings: *Object (4 properties) @@ -850,6 +877,9 @@ VirtualNetworkGateway: Resource │ │ └── Subnet: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sku: *Object (2 properties) │ │ ├── Name: *Enum (17 values) @@ -1176,7 +1206,7 @@ VirtualNetworkGateway: Resource └── "RouteBased" VirtualNetworksSubnet: Resource ├── Owner: VirtualNetwork -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AddressPrefix: *string │ ├── AddressPrefixes: string[] │ ├── ApplicationGatewayIpConfigurations: Object (1 property)[] @@ -1191,6 +1221,9 @@ VirtualNetworksSubnet: Resource │ │ └── Reference: *genruntime.ResourceReference │ ├── NetworkSecurityGroup: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateEndpointNetworkPolicies: *Enum (2 values) │ │ ├── "Disabled" @@ -1269,12 +1302,15 @@ VirtualNetworksSubnet: Resource └── Type: *string VirtualNetworksVirtualNetworkPeering: Resource ├── Owner: VirtualNetwork -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AllowForwardedTraffic: *bool │ ├── AllowGatewayTransit: *bool │ ├── AllowVirtualNetworkAccess: *bool │ ├── AzureName: string │ ├── DoNotVerifyRemoteGateways: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PeeringState: *Enum (3 values) │ │ ├── "Connected" diff --git a/v2/api/network/v1api20201101/virtual_network_gateway_types_gen.go b/v2/api/network/v1api20201101/virtual_network_gateway_types_gen.go index 7f119336da9..46c5ddcf3aa 100644 --- a/v2/api/network/v1api20201101/virtual_network_gateway_types_gen.go +++ b/v2/api/network/v1api20201101/virtual_network_gateway_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (gateway *VirtualNetworkGateway) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualNetworkGateway resource func (gateway *VirtualNetworkGateway) defaultImpl() { gateway.defaultAzureName() } +var _ configmaps.Exporter = &VirtualNetworkGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *VirtualNetworkGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworkGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *VirtualNetworkGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualNetworkGateway{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (gateway *VirtualNetworkGateway) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (gateway *VirtualNetworkGateway) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference} + return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference, gateway.validateSecretDestinations, gateway.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (gateway *VirtualNetworkGateway) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return gateway.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (gateway *VirtualNetworkGateway) validateConfigMapDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (gateway *VirtualNetworkGateway) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (gateway *VirtualNetworkGateway) validateSecretDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (gateway *VirtualNetworkGateway) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualNetworkGateway) @@ -365,6 +410,10 @@ type VirtualNetworkGateway_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualNetworkGatewayOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -672,6 +721,8 @@ func (gateway *VirtualNetworkGateway_Spec) PopulateFromARM(owner genruntime.Arbi gateway.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": gateway.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -908,6 +959,18 @@ func (gateway *VirtualNetworkGateway_Spec) AssignProperties_From_VirtualNetworkG // Location gateway.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualNetworkGatewayOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualNetworkGatewayOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualNetworkGatewayOperatorSpec() to populate field OperatorSpec") + } + gateway.OperatorSpec = &operatorSpec + } else { + gateway.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1090,6 +1153,18 @@ func (gateway *VirtualNetworkGateway_Spec) AssignProperties_To_VirtualNetworkGat // Location destination.Location = genruntime.ClonePointerToString(gateway.Location) + // OperatorSpec + if gateway.OperatorSpec != nil { + var operatorSpec storage.VirtualNetworkGatewayOperatorSpec + err := gateway.OperatorSpec.AssignProperties_To_VirtualNetworkGatewayOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualNetworkGatewayOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = gateway.OriginalVersion() @@ -3007,6 +3082,110 @@ func (configuration *VirtualNetworkGatewayIPConfiguration_STATUS) AssignProperti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworkGatewayOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualNetworkGatewayOperatorSpec populates our VirtualNetworkGatewayOperatorSpec from the provided source VirtualNetworkGatewayOperatorSpec +func (operator *VirtualNetworkGatewayOperatorSpec) AssignProperties_From_VirtualNetworkGatewayOperatorSpec(source *storage.VirtualNetworkGatewayOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualNetworkGatewayOperatorSpec populates the provided destination VirtualNetworkGatewayOperatorSpec from our VirtualNetworkGatewayOperatorSpec +func (operator *VirtualNetworkGatewayOperatorSpec) AssignProperties_To_VirtualNetworkGatewayOperatorSpec(destination *storage.VirtualNetworkGatewayOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"ExpressRoute","LocalGateway","Vpn"} type VirtualNetworkGatewayPropertiesFormat_GatewayType string diff --git a/v2/api/network/v1api20201101/virtual_network_gateway_types_gen_test.go b/v2/api/network/v1api20201101/virtual_network_gateway_types_gen_test.go index ab8ca72c98c..be512409202 100644 --- a/v2/api/network/v1api20201101/virtual_network_gateway_types_gen_test.go +++ b/v2/api/network/v1api20201101/virtual_network_gateway_types_gen_test.go @@ -1374,6 +1374,103 @@ func AddRelatedPropertyGeneratorsForVirtualNetworkGatewayIPConfiguration_STATUS( gens["Subnet"] = gen.PtrOf(SubResource_STATUSGenerator()) } +func Test_VirtualNetworkGatewayOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualNetworkGatewayOperatorSpec to VirtualNetworkGatewayOperatorSpec via AssignProperties_To_VirtualNetworkGatewayOperatorSpec & AssignProperties_From_VirtualNetworkGatewayOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualNetworkGatewayOperatorSpec, VirtualNetworkGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualNetworkGatewayOperatorSpec tests if a specific instance of VirtualNetworkGatewayOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualNetworkGatewayOperatorSpec(subject VirtualNetworkGatewayOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualNetworkGatewayOperatorSpec + err := copied.AssignProperties_To_VirtualNetworkGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualNetworkGatewayOperatorSpec + err = actual.AssignProperties_From_VirtualNetworkGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualNetworkGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworkGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec, VirtualNetworkGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec runs a test to see if a specific instance of VirtualNetworkGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworkGatewayOperatorSpec(subject VirtualNetworkGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworkGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworkGatewayOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworkGatewayOperatorSpecGenerator() +var virtualNetworkGatewayOperatorSpecGenerator gopter.Gen + +// VirtualNetworkGatewayOperatorSpecGenerator returns a generator of VirtualNetworkGatewayOperatorSpec instances for property testing. +func VirtualNetworkGatewayOperatorSpecGenerator() gopter.Gen { + if virtualNetworkGatewayOperatorSpecGenerator != nil { + return virtualNetworkGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworkGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworkGatewayOperatorSpec{}), generators) + + return virtualNetworkGatewayOperatorSpecGenerator +} + func Test_VirtualNetworkGatewaySku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1926,6 +2023,7 @@ func AddRelatedPropertyGeneratorsForVirtualNetworkGateway_Spec(gens map[string]g gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["GatewayDefaultSite"] = gen.PtrOf(SubResourceGenerator()) gens["IpConfigurations"] = gen.SliceOf(VirtualNetworkGatewayIPConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworkGatewayOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(VirtualNetworkGatewaySkuGenerator()) gens["VpnClientConfiguration"] = gen.PtrOf(VpnClientConfigurationGenerator()) } diff --git a/v2/api/network/v1api20201101/virtual_network_types_gen.go b/v2/api/network/v1api20201101/virtual_network_types_gen.go index 7bace49ed4c..8e8b13eb365 100644 --- a/v2/api/network/v1api20201101/virtual_network_types_gen.go +++ b/v2/api/network/v1api20201101/virtual_network_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (network *VirtualNetwork) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualNetwork resource func (network *VirtualNetwork) defaultImpl() { network.defaultAzureName() } +var _ configmaps.Exporter = &VirtualNetwork{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (network *VirtualNetwork) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if network.Spec.OperatorSpec == nil { + return nil + } + return network.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetwork{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (network *VirtualNetwork) SecretDestinationExpressions() []*core.DestinationExpression { + if network.Spec.OperatorSpec == nil { + return nil + } + return network.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualNetwork{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (network *VirtualNetwork) ValidateUpdate(old runtime.Object) (admission.War // createValidations validates the creation of the resource func (network *VirtualNetwork) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){network.validateResourceReferences, network.validateOwnerReference} + return []func() (admission.Warnings, error){network.validateResourceReferences, network.validateOwnerReference, network.validateSecretDestinations, network.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (network *VirtualNetwork) updateValidations() []func(old runtime.Object) (a func(old runtime.Object) (admission.Warnings, error) { return network.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return network.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return network.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (network *VirtualNetwork) validateConfigMapDestinations() (admission.Warnings, error) { + if network.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(network, nil, network.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (network *VirtualNetwork) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (network *VirtualNetwork) validateSecretDestinations() (admission.Warnings, error) { + if network.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(network, nil, network.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (network *VirtualNetwork) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualNetwork) @@ -358,6 +403,10 @@ type VirtualNetwork_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualNetworkOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -583,6 +632,8 @@ func (network *VirtualNetwork_Spec) PopulateFromARM(owner genruntime.ArbitraryOw network.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": network.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -754,6 +805,18 @@ func (network *VirtualNetwork_Spec) AssignProperties_From_VirtualNetwork_Spec(so // Location network.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualNetworkOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualNetworkOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualNetworkOperatorSpec() to populate field OperatorSpec") + } + network.OperatorSpec = &operatorSpec + } else { + network.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -874,6 +937,18 @@ func (network *VirtualNetwork_Spec) AssignProperties_To_VirtualNetwork_Spec(dest // Location destination.Location = genruntime.ClonePointerToString(network.Location) + // OperatorSpec + if network.OperatorSpec != nil { + var operatorSpec storage.VirtualNetworkOperatorSpec + err := network.OperatorSpec.AssignProperties_To_VirtualNetworkOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualNetworkOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = network.OriginalVersion() @@ -2012,6 +2087,110 @@ func (communities *VirtualNetworkBgpCommunities_STATUS) AssignProperties_To_Virt return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworkOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualNetworkOperatorSpec populates our VirtualNetworkOperatorSpec from the provided source VirtualNetworkOperatorSpec +func (operator *VirtualNetworkOperatorSpec) AssignProperties_From_VirtualNetworkOperatorSpec(source *storage.VirtualNetworkOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualNetworkOperatorSpec populates the provided destination VirtualNetworkOperatorSpec from our VirtualNetworkOperatorSpec +func (operator *VirtualNetworkOperatorSpec) AssignProperties_To_VirtualNetworkOperatorSpec(destination *storage.VirtualNetworkOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&VirtualNetwork{}, &VirtualNetworkList{}) } diff --git a/v2/api/network/v1api20201101/virtual_network_types_gen_test.go b/v2/api/network/v1api20201101/virtual_network_types_gen_test.go index f0e2117f7c0..323fd01f461 100644 --- a/v2/api/network/v1api20201101/virtual_network_types_gen_test.go +++ b/v2/api/network/v1api20201101/virtual_network_types_gen_test.go @@ -780,6 +780,103 @@ func AddIndependentPropertyGeneratorsForVirtualNetworkBgpCommunities_STATUS(gens gens["VirtualNetworkCommunity"] = gen.PtrOf(gen.AlphaString()) } +func Test_VirtualNetworkOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualNetworkOperatorSpec to VirtualNetworkOperatorSpec via AssignProperties_To_VirtualNetworkOperatorSpec & AssignProperties_From_VirtualNetworkOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualNetworkOperatorSpec, VirtualNetworkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualNetworkOperatorSpec tests if a specific instance of VirtualNetworkOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualNetworkOperatorSpec(subject VirtualNetworkOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualNetworkOperatorSpec + err := copied.AssignProperties_To_VirtualNetworkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualNetworkOperatorSpec + err = actual.AssignProperties_From_VirtualNetworkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualNetworkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworkOperatorSpec, VirtualNetworkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworkOperatorSpec runs a test to see if a specific instance of VirtualNetworkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworkOperatorSpec(subject VirtualNetworkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworkOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworkOperatorSpecGenerator() +var virtualNetworkOperatorSpecGenerator gopter.Gen + +// VirtualNetworkOperatorSpecGenerator returns a generator of VirtualNetworkOperatorSpec instances for property testing. +func VirtualNetworkOperatorSpecGenerator() gopter.Gen { + if virtualNetworkOperatorSpecGenerator != nil { + return virtualNetworkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworkOperatorSpec{}), generators) + + return virtualNetworkOperatorSpecGenerator +} + func Test_VirtualNetwork_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1043,4 +1140,5 @@ func AddRelatedPropertyGeneratorsForVirtualNetwork_Spec(gens map[string]gopter.G gens["DhcpOptions"] = gen.PtrOf(DhcpOptionsGenerator()) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpAllocations"] = gen.SliceOf(SubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworkOperatorSpecGenerator()) } diff --git a/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen.go b/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen.go index 160dcbd9491..6fabdeffe91 100644 --- a/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen.go +++ b/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (subnet *VirtualNetworksSubnet) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualNetworksSubnet resource func (subnet *VirtualNetworksSubnet) defaultImpl() { subnet.defaultAzureName() } +var _ configmaps.Exporter = &VirtualNetworksSubnet{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subnet *VirtualNetworksSubnet) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subnet.Spec.OperatorSpec == nil { + return nil + } + return subnet.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworksSubnet{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subnet *VirtualNetworksSubnet) SecretDestinationExpressions() []*core.DestinationExpression { + if subnet.Spec.OperatorSpec == nil { + return nil + } + return subnet.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualNetworksSubnet{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (subnet *VirtualNetworksSubnet) ValidateUpdate(old runtime.Object) (admissi // createValidations validates the creation of the resource func (subnet *VirtualNetworksSubnet) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subnet.validateResourceReferences, subnet.validateOwnerReference} + return []func() (admission.Warnings, error){subnet.validateResourceReferences, subnet.validateOwnerReference, subnet.validateSecretDestinations, subnet.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (subnet *VirtualNetworksSubnet) updateValidations() []func(old runtime.Obje func(old runtime.Object) (admission.Warnings, error) { return subnet.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return subnet.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return subnet.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subnet *VirtualNetworksSubnet) validateConfigMapDestinations() (admission.Warnings, error) { + if subnet.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subnet, nil, subnet.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (subnet *VirtualNetworksSubnet) validateResourceReferences() (admission.War return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (subnet *VirtualNetworksSubnet) validateSecretDestinations() (admission.Warnings, error) { + if subnet.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(subnet, nil, subnet.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (subnet *VirtualNetworksSubnet) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualNetworksSubnet) @@ -351,6 +396,10 @@ type VirtualNetworksSubnet_Spec struct { // NetworkSecurityGroup: The reference to the NetworkSecurityGroup resource. NetworkSecurityGroup *NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbedded `json:"networkSecurityGroup,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualNetworksSubnetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -580,6 +629,8 @@ func (subnet *VirtualNetworksSubnet_Spec) PopulateFromARM(owner genruntime.Arbit } } + // no assignment for property "OperatorSpec" + // Set property "Owner": subnet.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -792,6 +843,18 @@ func (subnet *VirtualNetworksSubnet_Spec) AssignProperties_From_VirtualNetworksS subnet.NetworkSecurityGroup = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualNetworksSubnetOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualNetworksSubnetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualNetworksSubnetOperatorSpec() to populate field OperatorSpec") + } + subnet.OperatorSpec = &operatorSpec + } else { + subnet.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -962,6 +1025,18 @@ func (subnet *VirtualNetworksSubnet_Spec) AssignProperties_To_VirtualNetworksSub destination.NetworkSecurityGroup = nil } + // OperatorSpec + if subnet.OperatorSpec != nil { + var operatorSpec storage.VirtualNetworksSubnetOperatorSpec + err := subnet.OperatorSpec.AssignProperties_To_VirtualNetworksSubnetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualNetworksSubnetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subnet.OriginalVersion() @@ -3639,6 +3714,110 @@ var subnetPropertiesFormat_PrivateLinkServiceNetworkPolicies_STATUS_Values = map "enabled": SubnetPropertiesFormat_PrivateLinkServiceNetworkPolicies_STATUS_Enabled, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworksSubnetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualNetworksSubnetOperatorSpec populates our VirtualNetworksSubnetOperatorSpec from the provided source VirtualNetworksSubnetOperatorSpec +func (operator *VirtualNetworksSubnetOperatorSpec) AssignProperties_From_VirtualNetworksSubnetOperatorSpec(source *storage.VirtualNetworksSubnetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualNetworksSubnetOperatorSpec populates the provided destination VirtualNetworksSubnetOperatorSpec from our VirtualNetworksSubnetOperatorSpec +func (operator *VirtualNetworksSubnetOperatorSpec) AssignProperties_To_VirtualNetworksSubnetOperatorSpec(destination *storage.VirtualNetworksSubnetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&VirtualNetworksSubnet{}, &VirtualNetworksSubnetList{}) } diff --git a/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen_test.go b/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen_test.go index da10c9e2f4c..915b0f47513 100644 --- a/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen_test.go +++ b/v2/api/network/v1api20201101/virtual_networks_subnet_types_gen_test.go @@ -1909,6 +1909,103 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksSubnet(gens map[string]gopter gens["Status"] = VirtualNetworksSubnet_STATUSGenerator() } +func Test_VirtualNetworksSubnetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualNetworksSubnetOperatorSpec to VirtualNetworksSubnetOperatorSpec via AssignProperties_To_VirtualNetworksSubnetOperatorSpec & AssignProperties_From_VirtualNetworksSubnetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualNetworksSubnetOperatorSpec, VirtualNetworksSubnetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualNetworksSubnetOperatorSpec tests if a specific instance of VirtualNetworksSubnetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualNetworksSubnetOperatorSpec(subject VirtualNetworksSubnetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualNetworksSubnetOperatorSpec + err := copied.AssignProperties_To_VirtualNetworksSubnetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualNetworksSubnetOperatorSpec + err = actual.AssignProperties_From_VirtualNetworksSubnetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualNetworksSubnetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworksSubnetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec, VirtualNetworksSubnetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec runs a test to see if a specific instance of VirtualNetworksSubnetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworksSubnetOperatorSpec(subject VirtualNetworksSubnetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworksSubnetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworksSubnetOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworksSubnetOperatorSpecGenerator() +var virtualNetworksSubnetOperatorSpecGenerator gopter.Gen + +// VirtualNetworksSubnetOperatorSpecGenerator returns a generator of VirtualNetworksSubnetOperatorSpec instances for property testing. +func VirtualNetworksSubnetOperatorSpecGenerator() gopter.Gen { + if virtualNetworksSubnetOperatorSpecGenerator != nil { + return virtualNetworksSubnetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworksSubnetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworksSubnetOperatorSpec{}), generators) + + return virtualNetworksSubnetOperatorSpecGenerator +} + func Test_VirtualNetworksSubnet_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2174,6 +2271,7 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksSubnet_Spec(gens map[string]g gens["IpAllocations"] = gen.SliceOf(SubResourceGenerator()) gens["NatGateway"] = gen.PtrOf(SubResourceGenerator()) gens["NetworkSecurityGroup"] = gen.PtrOf(NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworksSubnetOperatorSpecGenerator()) gens["RouteTable"] = gen.PtrOf(RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) gens["ServiceEndpointPolicies"] = gen.SliceOf(ServiceEndpointPolicySpec_VirtualNetworks_Subnet_SubResourceEmbeddedGenerator()) gens["ServiceEndpoints"] = gen.SliceOf(ServiceEndpointPropertiesFormatGenerator()) diff --git a/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen.go b/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen.go index 2ff9d030017..eaf32317718 100644 --- a/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen.go +++ b/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (peering *VirtualNetworksVirtualNetworkPeering) defaultAzureName() { // defaultImpl applies the code generated defaults to the VirtualNetworksVirtualNetworkPeering resource func (peering *VirtualNetworksVirtualNetworkPeering) defaultImpl() { peering.defaultAzureName() } +var _ configmaps.Exporter = &VirtualNetworksVirtualNetworkPeering{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (peering *VirtualNetworksVirtualNetworkPeering) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if peering.Spec.OperatorSpec == nil { + return nil + } + return peering.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &VirtualNetworksVirtualNetworkPeering{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (peering *VirtualNetworksVirtualNetworkPeering) SecretDestinationExpressions() []*core.DestinationExpression { + if peering.Spec.OperatorSpec == nil { + return nil + } + return peering.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &VirtualNetworksVirtualNetworkPeering{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (peering *VirtualNetworksVirtualNetworkPeering) ValidateUpdate(old runtime. // createValidations validates the creation of the resource func (peering *VirtualNetworksVirtualNetworkPeering) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){peering.validateResourceReferences, peering.validateOwnerReference} + return []func() (admission.Warnings, error){peering.validateResourceReferences, peering.validateOwnerReference, peering.validateSecretDestinations, peering.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (peering *VirtualNetworksVirtualNetworkPeering) updateValidations() []func( func(old runtime.Object) (admission.Warnings, error) { return peering.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return peering.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return peering.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (peering *VirtualNetworksVirtualNetworkPeering) validateConfigMapDestinations() (admission.Warnings, error) { + if peering.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(peering, nil, peering.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (peering *VirtualNetworksVirtualNetworkPeering) validateResourceReferences( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (peering *VirtualNetworksVirtualNetworkPeering) validateSecretDestinations() (admission.Warnings, error) { + if peering.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(peering, nil, peering.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (peering *VirtualNetworksVirtualNetworkPeering) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*VirtualNetworksVirtualNetworkPeering) @@ -344,6 +389,10 @@ type VirtualNetworksVirtualNetworkPeering_Spec struct { // DoNotVerifyRemoteGateways: If we need to verify the provisioning state of the remote gateway. DoNotVerifyRemoteGateways *bool `json:"doNotVerifyRemoteGateways,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *VirtualNetworksVirtualNetworkPeeringOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -499,6 +548,8 @@ func (peering *VirtualNetworksVirtualNetworkPeering_Spec) PopulateFromARM(owner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": peering.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -659,6 +710,18 @@ func (peering *VirtualNetworksVirtualNetworkPeering_Spec) AssignProperties_From_ peering.DoNotVerifyRemoteGateways = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec VirtualNetworksVirtualNetworkPeeringOperatorSpec + err := operatorSpec.AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec() to populate field OperatorSpec") + } + peering.OperatorSpec = &operatorSpec + } else { + peering.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -764,6 +827,18 @@ func (peering *VirtualNetworksVirtualNetworkPeering_Spec) AssignProperties_To_Vi destination.DoNotVerifyRemoteGateways = nil } + // OperatorSpec + if peering.OperatorSpec != nil { + var operatorSpec storage.VirtualNetworksVirtualNetworkPeeringOperatorSpec + err := peering.OperatorSpec.AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = peering.OriginalVersion() @@ -1484,6 +1559,110 @@ var virtualNetworkPeeringPropertiesFormat_PeeringState_STATUS_Values = map[strin "initiated": VirtualNetworkPeeringPropertiesFormat_PeeringState_STATUS_Initiated, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type VirtualNetworksVirtualNetworkPeeringOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec populates our VirtualNetworksVirtualNetworkPeeringOperatorSpec from the provided source VirtualNetworksVirtualNetworkPeeringOperatorSpec +func (operator *VirtualNetworksVirtualNetworkPeeringOperatorSpec) AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec(source *storage.VirtualNetworksVirtualNetworkPeeringOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec populates the provided destination VirtualNetworksVirtualNetworkPeeringOperatorSpec from our VirtualNetworksVirtualNetworkPeeringOperatorSpec +func (operator *VirtualNetworksVirtualNetworkPeeringOperatorSpec) AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec(destination *storage.VirtualNetworksVirtualNetworkPeeringOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&VirtualNetworksVirtualNetworkPeering{}, &VirtualNetworksVirtualNetworkPeeringList{}) } diff --git a/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen_test.go b/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen_test.go index 199a00b8d3b..39dcae18195 100644 --- a/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen_test.go +++ b/v2/api/network/v1api20201101/virtual_networks_virtual_network_peering_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering(gens ma gens["Status"] = VirtualNetworksVirtualNetworkPeering_STATUSGenerator() } +func Test_VirtualNetworksVirtualNetworkPeeringOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from VirtualNetworksVirtualNetworkPeeringOperatorSpec to VirtualNetworksVirtualNetworkPeeringOperatorSpec via AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec & AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec, VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec tests if a specific instance of VirtualNetworksVirtualNetworkPeeringOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec(subject VirtualNetworksVirtualNetworkPeeringOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.VirtualNetworksVirtualNetworkPeeringOperatorSpec + err := copied.AssignProperties_To_VirtualNetworksVirtualNetworkPeeringOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual VirtualNetworksVirtualNetworkPeeringOperatorSpec + err = actual.AssignProperties_From_VirtualNetworksVirtualNetworkPeeringOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_VirtualNetworksVirtualNetworkPeeringOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of VirtualNetworksVirtualNetworkPeeringOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec, VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec runs a test to see if a specific instance of VirtualNetworksVirtualNetworkPeeringOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForVirtualNetworksVirtualNetworkPeeringOperatorSpec(subject VirtualNetworksVirtualNetworkPeeringOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual VirtualNetworksVirtualNetworkPeeringOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of VirtualNetworksVirtualNetworkPeeringOperatorSpec instances for property testing - lazily instantiated by +// VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator() +var virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator gopter.Gen + +// VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator returns a generator of VirtualNetworksVirtualNetworkPeeringOperatorSpec instances for property testing. +func VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator() gopter.Gen { + if virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator != nil { + return virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator = gen.Struct(reflect.TypeOf(VirtualNetworksVirtualNetworkPeeringOperatorSpec{}), generators) + + return virtualNetworksVirtualNetworkPeeringOperatorSpecGenerator +} + func Test_VirtualNetworksVirtualNetworkPeering_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -419,6 +516,7 @@ func AddIndependentPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spe // AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForVirtualNetworksVirtualNetworkPeering_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(VirtualNetworksVirtualNetworkPeeringOperatorSpecGenerator()) gens["RemoteAddressSpace"] = gen.PtrOf(AddressSpaceGenerator()) gens["RemoteBgpCommunities"] = gen.PtrOf(VirtualNetworkBgpCommunitiesGenerator()) gens["RemoteVirtualNetwork"] = gen.PtrOf(SubResourceGenerator()) diff --git a/v2/api/network/v1api20201101/zz_generated.deepcopy.go b/v2/api/network/v1api20201101/zz_generated.deepcopy.go index de2c7f24d46..94a8cee358f 100644 --- a/v2/api/network/v1api20201101/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20201101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20201101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1571,6 +1572,43 @@ func (in *LoadBalancerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancerOperatorSpec) DeepCopyInto(out *LoadBalancerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerOperatorSpec. +func (in *LoadBalancerOperatorSpec) DeepCopy() *LoadBalancerOperatorSpec { + if in == nil { + return nil + } + out := new(LoadBalancerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancerSku) DeepCopyInto(out *LoadBalancerSku) { *out = *in @@ -1792,6 +1830,11 @@ func (in *LoadBalancer_Spec) DeepCopyInto(out *LoadBalancer_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(LoadBalancerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.OutboundRules != nil { in, out := &in.OutboundRules, &out.OutboundRules *out = make([]OutboundRule, len(*in)) @@ -1894,6 +1937,43 @@ func (in *LoadBalancersInboundNatRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancersInboundNatRuleOperatorSpec) DeepCopyInto(out *LoadBalancersInboundNatRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancersInboundNatRuleOperatorSpec. +func (in *LoadBalancersInboundNatRuleOperatorSpec) DeepCopy() *LoadBalancersInboundNatRuleOperatorSpec { + if in == nil { + return nil + } + out := new(LoadBalancersInboundNatRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LoadBalancersInboundNatRule_STATUS) DeepCopyInto(out *LoadBalancersInboundNatRule_STATUS) { *out = *in @@ -2014,6 +2094,11 @@ func (in *LoadBalancersInboundNatRule_Spec) DeepCopyInto(out *LoadBalancersInbou *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(LoadBalancersInboundNatRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2635,6 +2720,43 @@ func (in *NetworkInterfaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkInterfaceOperatorSpec) DeepCopyInto(out *NetworkInterfaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkInterfaceOperatorSpec. +func (in *NetworkInterfaceOperatorSpec) DeepCopy() *NetworkInterfaceOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkInterfaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *NetworkInterfaceTapConfiguration_STATUS_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -2868,6 +2990,11 @@ func (in *NetworkInterface_Spec) DeepCopyInto(out *NetworkInterface_Spec) { *out = new(NetworkInterfacePropertiesFormat_NicType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkInterfaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2956,6 +3083,43 @@ func (in *NetworkSecurityGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSecurityGroupOperatorSpec) DeepCopyInto(out *NetworkSecurityGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSecurityGroupOperatorSpec. +func (in *NetworkSecurityGroupOperatorSpec) DeepCopy() *NetworkSecurityGroupOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkSecurityGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *NetworkSecurityGroupSpec_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -3136,6 +3300,11 @@ func (in *NetworkSecurityGroup_Spec) DeepCopyInto(out *NetworkSecurityGroup_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkSecurityGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3219,6 +3388,43 @@ func (in *NetworkSecurityGroupsSecurityRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSecurityGroupsSecurityRuleOperatorSpec) DeepCopyInto(out *NetworkSecurityGroupsSecurityRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSecurityGroupsSecurityRuleOperatorSpec. +func (in *NetworkSecurityGroupsSecurityRuleOperatorSpec) DeepCopy() *NetworkSecurityGroupsSecurityRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NetworkSecurityGroupsSecurityRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NetworkSecurityGroupsSecurityRule_STATUS) DeepCopyInto(out *NetworkSecurityGroupsSecurityRule_STATUS) { *out = *in @@ -3390,6 +3596,11 @@ func (in *NetworkSecurityGroupsSecurityRule_Spec) DeepCopyInto(out *NetworkSecur *out = new(SecurityRuleDirection) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NetworkSecurityGroupsSecurityRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3884,6 +4095,43 @@ func (in *PublicIPAddressList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PublicIPAddressOperatorSpec) DeepCopyInto(out *PublicIPAddressOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PublicIPAddressOperatorSpec. +func (in *PublicIPAddressOperatorSpec) DeepCopy() *PublicIPAddressOperatorSpec { + if in == nil { + return nil + } + out := new(PublicIPAddressOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PublicIPAddressSku) DeepCopyInto(out *PublicIPAddressSku) { *out = *in @@ -4220,6 +4468,11 @@ func (in *PublicIPAddress_Spec) DeepCopyInto(out *PublicIPAddress_Spec) { *out = new(NatGatewaySpec_PublicIPAddress_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PublicIPAddressOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4413,6 +4666,43 @@ func (in *RouteTableList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteTableOperatorSpec) DeepCopyInto(out *RouteTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTableOperatorSpec. +func (in *RouteTableOperatorSpec) DeepCopy() *RouteTableOperatorSpec { + if in == nil { + return nil + } + out := new(RouteTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbedded) DeepCopyInto(out *RouteTableSpec_VirtualNetworks_Subnet_SubResourceEmbedded) { *out = *in @@ -4535,6 +4825,11 @@ func (in *RouteTable_Spec) DeepCopyInto(out *RouteTable_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4618,6 +4913,43 @@ func (in *RouteTablesRouteList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteTablesRouteOperatorSpec) DeepCopyInto(out *RouteTablesRouteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTablesRouteOperatorSpec. +func (in *RouteTablesRouteOperatorSpec) DeepCopy() *RouteTablesRouteOperatorSpec { + if in == nil { + return nil + } + out := new(RouteTablesRouteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RouteTablesRoute_STATUS) DeepCopyInto(out *RouteTablesRoute_STATUS) { *out = *in @@ -4703,6 +5035,11 @@ func (in *RouteTablesRoute_Spec) DeepCopyInto(out *RouteTablesRoute_Spec) { *out = new(RouteNextHopType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(RouteTablesRouteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5216,6 +5553,43 @@ func (in *VirtualNetworkGatewayList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworkGatewayOperatorSpec) DeepCopyInto(out *VirtualNetworkGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworkGatewayOperatorSpec. +func (in *VirtualNetworkGatewayOperatorSpec) DeepCopy() *VirtualNetworkGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworkGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworkGatewaySku) DeepCopyInto(out *VirtualNetworkGatewaySku) { *out = *in @@ -5477,6 +5851,11 @@ func (in *VirtualNetworkGateway_Spec) DeepCopyInto(out *VirtualNetworkGateway_Sp *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworkGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5558,6 +5937,43 @@ func (in *VirtualNetworkList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworkOperatorSpec) DeepCopyInto(out *VirtualNetworkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworkOperatorSpec. +func (in *VirtualNetworkOperatorSpec) DeepCopy() *VirtualNetworkOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworkTapSpec_NetworkInterface_SubResourceEmbedded) DeepCopyInto(out *VirtualNetworkTapSpec_NetworkInterface_SubResourceEmbedded) { *out = *in @@ -5754,6 +6170,11 @@ func (in *VirtualNetwork_Spec) DeepCopyInto(out *VirtualNetwork_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5837,6 +6258,43 @@ func (in *VirtualNetworksSubnetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworksSubnetOperatorSpec) DeepCopyInto(out *VirtualNetworksSubnetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworksSubnetOperatorSpec. +func (in *VirtualNetworksSubnetOperatorSpec) DeepCopy() *VirtualNetworksSubnetOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworksSubnetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworksSubnet_STATUS) DeepCopyInto(out *VirtualNetworksSubnet_STATUS) { *out = *in @@ -6038,6 +6496,11 @@ func (in *VirtualNetworksSubnet_Spec) DeepCopyInto(out *VirtualNetworksSubnet_Sp *out = new(NetworkSecurityGroupSpec_VirtualNetworks_Subnet_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworksSubnetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6143,6 +6606,43 @@ func (in *VirtualNetworksVirtualNetworkPeeringList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VirtualNetworksVirtualNetworkPeeringOperatorSpec) DeepCopyInto(out *VirtualNetworksVirtualNetworkPeeringOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VirtualNetworksVirtualNetworkPeeringOperatorSpec. +func (in *VirtualNetworksVirtualNetworkPeeringOperatorSpec) DeepCopy() *VirtualNetworksVirtualNetworkPeeringOperatorSpec { + if in == nil { + return nil + } + out := new(VirtualNetworksVirtualNetworkPeeringOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualNetworksVirtualNetworkPeering_STATUS) DeepCopyInto(out *VirtualNetworksVirtualNetworkPeering_STATUS) { *out = *in @@ -6263,6 +6763,11 @@ func (in *VirtualNetworksVirtualNetworkPeering_Spec) DeepCopyInto(out *VirtualNe *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(VirtualNetworksVirtualNetworkPeeringOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20220401/storage/structure.txt b/v2/api/network/v1api20220401/storage/structure.txt index be74789c0f1..68bd059b09d 100644 --- a/v2/api/network/v1api20220401/storage/structure.txt +++ b/v2/api/network/v1api20220401/storage/structure.txt @@ -31,11 +31,13 @@ TrafficManagerProfile: Resource │ │ ├── Protocol: *string │ │ ├── TimeoutInSeconds: *int │ │ └── ToleratedNumberOfFailures: *int -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── DnsConfigFqdn: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProfileStatus: *string @@ -84,7 +86,7 @@ TrafficManagerProfile: Resource └── Type: *string TrafficManagerProfilesAzureEndpoint: Resource ├── Owner: network/v1api20220401.TrafficManagerProfile -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AlwaysServe: *string │ ├── AzureName: string │ ├── CustomHeaders: Object (3 properties)[] @@ -98,6 +100,10 @@ TrafficManagerProfilesAzureEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int @@ -140,7 +146,7 @@ TrafficManagerProfilesAzureEndpoint: Resource └── Weight: *int TrafficManagerProfilesExternalEndpoint: Resource ├── Owner: network/v1api20220401.TrafficManagerProfile -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AlwaysServe: *string │ ├── AzureName: string │ ├── CustomHeaders: Object (3 properties)[] @@ -154,6 +160,10 @@ TrafficManagerProfilesExternalEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int @@ -196,7 +206,7 @@ TrafficManagerProfilesExternalEndpoint: Resource └── Weight: *int TrafficManagerProfilesNestedEndpoint: Resource ├── Owner: network/v1api20220401.TrafficManagerProfile -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AlwaysServe: *string │ ├── AzureName: string │ ├── CustomHeaders: Object (3 properties)[] @@ -210,6 +220,10 @@ TrafficManagerProfilesNestedEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profile_types_gen.go b/v2/api/network/v1api20220401/storage/traffic_manager_profile_types_gen.go index a98f8cf5e76..0c1cdc6adbb 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profile_types_gen.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profile_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (profile *TrafficManagerProfile) SetConditions(conditions conditions.Condit profile.Status.Conditions = conditions } +var _ configmaps.Exporter = &TrafficManagerProfile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *TrafficManagerProfile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *TrafficManagerProfile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &TrafficManagerProfile{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -311,8 +333,10 @@ type MonitorConfig_STATUS struct { // Storage version of v1api20220401.TrafficManagerProfileOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type TrafficManagerProfileOperatorSpec struct { - ConfigMaps *TrafficManagerProfileOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *TrafficManagerProfileOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20220401.MonitorConfig_CustomHeaders diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen.go index a164b31e406..b56feeaf336 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint) SetConditions(conditions co endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &TrafficManagerProfilesAzureEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesAzureEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesAzureEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesAzureEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrafficManagerProfilesAzureEndpoint{} // AzureName returns the Azure name of the resource @@ -144,16 +167,17 @@ type TrafficManagerProfilesAzureEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` - EndpointLocation *string `json:"endpointLocation,omitempty"` - EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` - EndpointStatus *string `json:"endpointStatus,omitempty"` - GeoMapping []string `json:"geoMapping,omitempty"` - MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` - MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` - MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` + EndpointLocation *string `json:"endpointLocation,omitempty"` + EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` + EndpointStatus *string `json:"endpointStatus,omitempty"` + GeoMapping []string `json:"geoMapping,omitempty"` + MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` + MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` + MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + OperatorSpec *TrafficManagerProfilesAzureEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -265,6 +289,14 @@ type EndpointProperties_Subnets_STATUS struct { Scope *int `json:"scope,omitempty"` } +// Storage version of v1api20220401.TrafficManagerProfilesAzureEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesAzureEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesAzureEndpoint{}, &TrafficManagerProfilesAzureEndpointList{}) } diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen_test.go index f7bf0a43a17..efcc5cb0feb 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_azure_endpoint_types_gen_test.go @@ -329,6 +329,61 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint(gens map gens["Status"] = TrafficManagerProfilesAzureEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesAzureEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesAzureEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec, TrafficManagerProfilesAzureEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesAzureEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec(subject TrafficManagerProfilesAzureEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesAzureEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesAzureEndpointOperatorSpec instances for property testing - lazily instantiated by +// TrafficManagerProfilesAzureEndpointOperatorSpecGenerator() +var trafficManagerProfilesAzureEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesAzureEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesAzureEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesAzureEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesAzureEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesAzureEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesAzureEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesAzureEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesAzureEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesAzureEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -505,5 +560,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec // AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesAzureEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen.go index ff1f36e815b..fc6f9743a48 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint) SetConditions(conditions endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &TrafficManagerProfilesExternalEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesExternalEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesExternalEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesExternalEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrafficManagerProfilesExternalEndpoint{} // AzureName returns the Azure name of the resource @@ -144,16 +167,17 @@ type TrafficManagerProfilesExternalEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` - EndpointLocation *string `json:"endpointLocation,omitempty"` - EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` - EndpointStatus *string `json:"endpointStatus,omitempty"` - GeoMapping []string `json:"geoMapping,omitempty"` - MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` - MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` - MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` + EndpointLocation *string `json:"endpointLocation,omitempty"` + EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` + EndpointStatus *string `json:"endpointStatus,omitempty"` + GeoMapping []string `json:"geoMapping,omitempty"` + MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` + MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` + MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + OperatorSpec *TrafficManagerProfilesExternalEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -235,6 +259,14 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint_STATUS) ConvertStatusTo(d return destination.ConvertStatusFrom(endpoint) } +// Storage version of v1api20220401.TrafficManagerProfilesExternalEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesExternalEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesExternalEndpoint{}, &TrafficManagerProfilesExternalEndpointList{}) } diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen_test.go index 26a83f00795..82a18ef10ee 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_external_endpoint_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint(gens gens["Status"] = TrafficManagerProfilesExternalEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesExternalEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesExternalEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec, TrafficManagerProfilesExternalEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesExternalEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec(subject TrafficManagerProfilesExternalEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesExternalEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesExternalEndpointOperatorSpec instances for property testing - lazily instantiated +// by TrafficManagerProfilesExternalEndpointOperatorSpecGenerator() +var trafficManagerProfilesExternalEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesExternalEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesExternalEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesExternalEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesExternalEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesExternalEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesExternalEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesExternalEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesExternalEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesExternalEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,5 +310,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_S // AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesExternalEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen.go index 4742288e812..e84c360cddc 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint) SetConditions(conditions c endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &TrafficManagerProfilesNestedEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesNestedEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesNestedEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesNestedEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &TrafficManagerProfilesNestedEndpoint{} // AzureName returns the Azure name of the resource @@ -144,16 +167,17 @@ type TrafficManagerProfilesNestedEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` - EndpointLocation *string `json:"endpointLocation,omitempty"` - EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` - EndpointStatus *string `json:"endpointStatus,omitempty"` - GeoMapping []string `json:"geoMapping,omitempty"` - MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` - MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` - MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CustomHeaders []EndpointProperties_CustomHeaders `json:"customHeaders,omitempty"` + EndpointLocation *string `json:"endpointLocation,omitempty"` + EndpointMonitorStatus *string `json:"endpointMonitorStatus,omitempty"` + EndpointStatus *string `json:"endpointStatus,omitempty"` + GeoMapping []string `json:"geoMapping,omitempty"` + MinChildEndpoints *int `json:"minChildEndpoints,omitempty"` + MinChildEndpointsIPv4 *int `json:"minChildEndpointsIPv4,omitempty"` + MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + OperatorSpec *TrafficManagerProfilesNestedEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -235,6 +259,14 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint_STATUS) ConvertStatusTo(des return destination.ConvertStatusFrom(endpoint) } +// Storage version of v1api20220401.TrafficManagerProfilesNestedEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesNestedEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesNestedEndpoint{}, &TrafficManagerProfilesNestedEndpointList{}) } diff --git a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen_test.go index 7bcb18199cf..1911bd7e19f 100644 --- a/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/storage/traffic_manager_profiles_nested_endpoint_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint(gens ma gens["Status"] = TrafficManagerProfilesNestedEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesNestedEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesNestedEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec, TrafficManagerProfilesNestedEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesNestedEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec(subject TrafficManagerProfilesNestedEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesNestedEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesNestedEndpointOperatorSpec instances for property testing - lazily instantiated by +// TrafficManagerProfilesNestedEndpointOperatorSpecGenerator() +var trafficManagerProfilesNestedEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesNestedEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesNestedEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesNestedEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesNestedEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesNestedEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesNestedEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesNestedEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesNestedEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesNestedEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -255,5 +310,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spe // AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesNestedEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20220401/storage/zz_generated.deepcopy.go index 5de7ecc3d03..67fd9abc328 100644 --- a/v2/api/network/v1api20220401/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20220401/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -608,6 +609,17 @@ func (in *TrafficManagerProfileOperatorConfigMaps) DeepCopy() *TrafficManagerPro // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfileOperatorSpec) DeepCopyInto(out *TrafficManagerProfileOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(TrafficManagerProfileOperatorConfigMaps) @@ -620,6 +632,17 @@ func (in *TrafficManagerProfileOperatorSpec) DeepCopyInto(out *TrafficManagerPro (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileOperatorSpec. @@ -873,6 +896,50 @@ func (in *TrafficManagerProfilesAzureEndpointList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesAzureEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesAzureEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesAzureEndpointOperatorSpec. +func (in *TrafficManagerProfilesAzureEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesAzureEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesAzureEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesAzureEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesAzureEndpoint_STATUS) { *out = *in @@ -1041,6 +1108,11 @@ func (in *TrafficManagerProfilesAzureEndpoint_Spec) DeepCopyInto(out *TrafficMan *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesAzureEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1156,6 +1228,50 @@ func (in *TrafficManagerProfilesExternalEndpointList) DeepCopyObject() runtime.O return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesExternalEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesExternalEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesExternalEndpointOperatorSpec. +func (in *TrafficManagerProfilesExternalEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesExternalEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesExternalEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesExternalEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesExternalEndpoint_STATUS) { *out = *in @@ -1324,6 +1440,11 @@ func (in *TrafficManagerProfilesExternalEndpoint_Spec) DeepCopyInto(out *Traffic *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesExternalEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1439,6 +1560,50 @@ func (in *TrafficManagerProfilesNestedEndpointList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesNestedEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesNestedEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesNestedEndpointOperatorSpec. +func (in *TrafficManagerProfilesNestedEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesNestedEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesNestedEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesNestedEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesNestedEndpoint_STATUS) { *out = *in @@ -1607,6 +1772,11 @@ func (in *TrafficManagerProfilesNestedEndpoint_Spec) DeepCopyInto(out *TrafficMa *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesNestedEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20220401/structure.txt b/v2/api/network/v1api20220401/structure.txt index caf8411d271..4b2601cacae 100644 --- a/v2/api/network/v1api20220401/structure.txt +++ b/v2/api/network/v1api20220401/structure.txt @@ -39,9 +39,11 @@ TrafficManagerProfile: Resource │ │ │ └── "TCP" │ │ ├── TimeoutInSeconds: *int │ │ └── ToleratedNumberOfFailures: *int -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── DnsConfigFqdn: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── DnsConfigFqdn: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProfileStatus: *Enum (2 values) │ │ ├── "Disabled" @@ -114,7 +116,7 @@ TrafficManagerProfile: Resource └── Type: *string TrafficManagerProfilesAzureEndpoint: Resource ├── Owner: TrafficManagerProfile -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AlwaysServe: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" @@ -138,6 +140,9 @@ TrafficManagerProfilesAzureEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int │ ├── Subnets: Object (3 properties)[] @@ -185,7 +190,7 @@ TrafficManagerProfilesAzureEndpoint: Resource └── Weight: *int TrafficManagerProfilesExternalEndpoint: Resource ├── Owner: TrafficManagerProfile -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AlwaysServe: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" @@ -209,6 +214,9 @@ TrafficManagerProfilesExternalEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int │ ├── Subnets: Object (3 properties)[] @@ -256,7 +264,7 @@ TrafficManagerProfilesExternalEndpoint: Resource └── Weight: *int TrafficManagerProfilesNestedEndpoint: Resource ├── Owner: TrafficManagerProfile -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AlwaysServe: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" @@ -280,6 +288,9 @@ TrafficManagerProfilesNestedEndpoint: Resource │ ├── MinChildEndpoints: *int │ ├── MinChildEndpointsIPv4: *int │ ├── MinChildEndpointsIPv6: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Priority: *int │ ├── Subnets: Object (3 properties)[] diff --git a/v2/api/network/v1api20220401/traffic_manager_profile_types_gen.go b/v2/api/network/v1api20220401/traffic_manager_profile_types_gen.go index 74c71de9ab2..e23aecec16c 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profile_types_gen.go +++ b/v2/api/network/v1api20220401/traffic_manager_profile_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (profile *TrafficManagerProfile) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrafficManagerProfile resource func (profile *TrafficManagerProfile) defaultImpl() { profile.defaultAzureName() } +var _ configmaps.Exporter = &TrafficManagerProfile{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (profile *TrafficManagerProfile) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfile{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (profile *TrafficManagerProfile) SecretDestinationExpressions() []*core.DestinationExpression { + if profile.Spec.OperatorSpec == nil { + return nil + } + return profile.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &TrafficManagerProfile{} // InitializeSpec initializes the spec for this resource from the given status @@ -233,7 +255,7 @@ func (profile *TrafficManagerProfile) ValidateUpdate(old runtime.Object) (admiss // createValidations validates the creation of the resource func (profile *TrafficManagerProfile) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference, profile.validateConfigMapDestinations} + return []func() (admission.Warnings, error){profile.validateResourceReferences, profile.validateOwnerReference, profile.validateSecretDestinations, profile.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -251,6 +273,9 @@ func (profile *TrafficManagerProfile) updateValidations() []func(old runtime.Obj func(old runtime.Object) (admission.Warnings, error) { return profile.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return profile.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return profile.validateConfigMapDestinations() }, @@ -262,13 +287,13 @@ func (profile *TrafficManagerProfile) validateConfigMapDestinations() (admission if profile.Spec.OperatorSpec == nil { return nil, nil } - if profile.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - profile.Spec.OperatorSpec.ConfigMaps.DnsConfigFqdn, + var toValidate []*genruntime.ConfigMapDestination + if profile.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + profile.Spec.OperatorSpec.ConfigMaps.DnsConfigFqdn, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(profile, toValidate, profile.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -285,6 +310,14 @@ func (profile *TrafficManagerProfile) validateResourceReferences() (admission.Wa return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (profile *TrafficManagerProfile) validateSecretDestinations() (admission.Warnings, error) { + if profile.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(profile, nil, profile.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (profile *TrafficManagerProfile) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrafficManagerProfile) @@ -2559,13 +2592,37 @@ var profileProperties_TrafficViewEnrollmentStatus_STATUS_Values = map[string]Pro // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type TrafficManagerProfileOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *TrafficManagerProfileOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_TrafficManagerProfileOperatorSpec populates our TrafficManagerProfileOperatorSpec from the provided source TrafficManagerProfileOperatorSpec func (operator *TrafficManagerProfileOperatorSpec) AssignProperties_From_TrafficManagerProfileOperatorSpec(source *storage.TrafficManagerProfileOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap TrafficManagerProfileOperatorConfigMaps @@ -2578,6 +2635,24 @@ func (operator *TrafficManagerProfileOperatorSpec) AssignProperties_From_Traffic operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2587,6 +2662,24 @@ func (operator *TrafficManagerProfileOperatorSpec) AssignProperties_To_TrafficMa // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.TrafficManagerProfileOperatorConfigMaps @@ -2599,6 +2692,24 @@ func (operator *TrafficManagerProfileOperatorSpec) AssignProperties_To_TrafficMa destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen.go b/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen.go index 536e7b811a3..d95fb524220 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrafficManagerProfilesAzureEndpoint resource func (endpoint *TrafficManagerProfilesAzureEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &TrafficManagerProfilesAzureEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesAzureEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesAzureEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesAzureEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &TrafficManagerProfilesAzureEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint) ValidateUpdate(old runtime. // createValidations validates the creation of the resource func (endpoint *TrafficManagerProfilesAzureEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint) updateValidations() []func( func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *TrafficManagerProfilesAzureEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint) validateResourceReferences( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *TrafficManagerProfilesAzureEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *TrafficManagerProfilesAzureEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrafficManagerProfilesAzureEndpoint) @@ -366,6 +411,10 @@ type TrafficManagerProfilesAzureEndpoint_Spec struct { // 'NestedEndpoints'. MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrafficManagerProfilesAzureEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -610,6 +659,8 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint_Spec) PopulateFromARM(owner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -784,6 +835,18 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint_Spec) AssignProperties_From_ // MinChildEndpointsIPv6 endpoint.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(source.MinChildEndpointsIPv6) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrafficManagerProfilesAzureEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -899,6 +962,18 @@ func (endpoint *TrafficManagerProfilesAzureEndpoint_Spec) AssignProperties_To_Tr // MinChildEndpointsIPv6 destination.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(endpoint.MinChildEndpointsIPv6) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.TrafficManagerProfilesAzureEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -2092,6 +2167,110 @@ func (subnets *EndpointProperties_Subnets_STATUS) AssignProperties_To_EndpointPr return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesAzureEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec populates our TrafficManagerProfilesAzureEndpointOperatorSpec from the provided source TrafficManagerProfilesAzureEndpointOperatorSpec +func (operator *TrafficManagerProfilesAzureEndpointOperatorSpec) AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec(source *storage.TrafficManagerProfilesAzureEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec populates the provided destination TrafficManagerProfilesAzureEndpointOperatorSpec from our TrafficManagerProfilesAzureEndpointOperatorSpec +func (operator *TrafficManagerProfilesAzureEndpointOperatorSpec) AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec(destination *storage.TrafficManagerProfilesAzureEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesAzureEndpoint{}, &TrafficManagerProfilesAzureEndpointList{}) } diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen_test.go index a3f12e832f4..9c97c4f5211 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_azure_endpoint_types_gen_test.go @@ -583,6 +583,103 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint(gens map gens["Status"] = TrafficManagerProfilesAzureEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesAzureEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrafficManagerProfilesAzureEndpointOperatorSpec to TrafficManagerProfilesAzureEndpointOperatorSpec via AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec & AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrafficManagerProfilesAzureEndpointOperatorSpec, TrafficManagerProfilesAzureEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrafficManagerProfilesAzureEndpointOperatorSpec tests if a specific instance of TrafficManagerProfilesAzureEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrafficManagerProfilesAzureEndpointOperatorSpec(subject TrafficManagerProfilesAzureEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.TrafficManagerProfilesAzureEndpointOperatorSpec + err := copied.AssignProperties_To_TrafficManagerProfilesAzureEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrafficManagerProfilesAzureEndpointOperatorSpec + err = actual.AssignProperties_From_TrafficManagerProfilesAzureEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrafficManagerProfilesAzureEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesAzureEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec, TrafficManagerProfilesAzureEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesAzureEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesAzureEndpointOperatorSpec(subject TrafficManagerProfilesAzureEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesAzureEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesAzureEndpointOperatorSpec instances for property testing - lazily instantiated by +// TrafficManagerProfilesAzureEndpointOperatorSpecGenerator() +var trafficManagerProfilesAzureEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesAzureEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesAzureEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesAzureEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesAzureEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesAzureEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesAzureEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesAzureEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesAzureEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesAzureEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -856,5 +953,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec // AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesAzureEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesAzureEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen.go b/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen.go index 5345bd2ad6d..712b76e64cd 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrafficManagerProfilesExternalEndpoint resource func (endpoint *TrafficManagerProfilesExternalEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &TrafficManagerProfilesExternalEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesExternalEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesExternalEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesExternalEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &TrafficManagerProfilesExternalEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint) ValidateUpdate(old runti // createValidations validates the creation of the resource func (endpoint *TrafficManagerProfilesExternalEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint) updateValidations() []fu func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *TrafficManagerProfilesExternalEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint) validateResourceReferenc return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *TrafficManagerProfilesExternalEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *TrafficManagerProfilesExternalEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrafficManagerProfilesExternalEndpoint) @@ -366,6 +411,10 @@ type TrafficManagerProfilesExternalEndpoint_Spec struct { // 'NestedEndpoints'. MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrafficManagerProfilesExternalEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -610,6 +659,8 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint_Spec) PopulateFromARM(own } } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -784,6 +835,18 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint_Spec) AssignProperties_Fr // MinChildEndpointsIPv6 endpoint.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(source.MinChildEndpointsIPv6) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrafficManagerProfilesExternalEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -899,6 +962,18 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint_Spec) AssignProperties_To // MinChildEndpointsIPv6 destination.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(endpoint.MinChildEndpointsIPv6) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.TrafficManagerProfilesExternalEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -1592,6 +1667,110 @@ func (endpoint *TrafficManagerProfilesExternalEndpoint_STATUS) AssignProperties_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesExternalEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec populates our TrafficManagerProfilesExternalEndpointOperatorSpec from the provided source TrafficManagerProfilesExternalEndpointOperatorSpec +func (operator *TrafficManagerProfilesExternalEndpointOperatorSpec) AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec(source *storage.TrafficManagerProfilesExternalEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec populates the provided destination TrafficManagerProfilesExternalEndpointOperatorSpec from our TrafficManagerProfilesExternalEndpointOperatorSpec +func (operator *TrafficManagerProfilesExternalEndpointOperatorSpec) AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec(destination *storage.TrafficManagerProfilesExternalEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesExternalEndpoint{}, &TrafficManagerProfilesExternalEndpointList{}) } diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen_test.go index 03b9f09f9af..51bf45e35e1 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_external_endpoint_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint(gens gens["Status"] = TrafficManagerProfilesExternalEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesExternalEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrafficManagerProfilesExternalEndpointOperatorSpec to TrafficManagerProfilesExternalEndpointOperatorSpec via AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec & AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrafficManagerProfilesExternalEndpointOperatorSpec, TrafficManagerProfilesExternalEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrafficManagerProfilesExternalEndpointOperatorSpec tests if a specific instance of TrafficManagerProfilesExternalEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrafficManagerProfilesExternalEndpointOperatorSpec(subject TrafficManagerProfilesExternalEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.TrafficManagerProfilesExternalEndpointOperatorSpec + err := copied.AssignProperties_To_TrafficManagerProfilesExternalEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrafficManagerProfilesExternalEndpointOperatorSpec + err = actual.AssignProperties_From_TrafficManagerProfilesExternalEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrafficManagerProfilesExternalEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesExternalEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec, TrafficManagerProfilesExternalEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesExternalEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesExternalEndpointOperatorSpec(subject TrafficManagerProfilesExternalEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesExternalEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesExternalEndpointOperatorSpec instances for property testing - lazily instantiated +// by TrafficManagerProfilesExternalEndpointOperatorSpecGenerator() +var trafficManagerProfilesExternalEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesExternalEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesExternalEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesExternalEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesExternalEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesExternalEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesExternalEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesExternalEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesExternalEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesExternalEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -438,5 +535,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_S // AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesExternalEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesExternalEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen.go b/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen.go index 0f7b66aec88..a2ecebcc925 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the TrafficManagerProfilesNestedEndpoint resource func (endpoint *TrafficManagerProfilesNestedEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &TrafficManagerProfilesNestedEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *TrafficManagerProfilesNestedEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &TrafficManagerProfilesNestedEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *TrafficManagerProfilesNestedEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &TrafficManagerProfilesNestedEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint) ValidateUpdate(old runtime // createValidations validates the creation of the resource func (endpoint *TrafficManagerProfilesNestedEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint) updateValidations() []func func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *TrafficManagerProfilesNestedEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint) validateResourceReferences return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *TrafficManagerProfilesNestedEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *TrafficManagerProfilesNestedEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*TrafficManagerProfilesNestedEndpoint) @@ -366,6 +411,10 @@ type TrafficManagerProfilesNestedEndpoint_Spec struct { // 'NestedEndpoints'. MinChildEndpointsIPv6 *int `json:"minChildEndpointsIPv6,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *TrafficManagerProfilesNestedEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -610,6 +659,8 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint_Spec) PopulateFromARM(owner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -784,6 +835,18 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint_Spec) AssignProperties_From // MinChildEndpointsIPv6 endpoint.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(source.MinChildEndpointsIPv6) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec TrafficManagerProfilesNestedEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -899,6 +962,18 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint_Spec) AssignProperties_To_T // MinChildEndpointsIPv6 destination.MinChildEndpointsIPv6 = genruntime.ClonePointerToInt(endpoint.MinChildEndpointsIPv6) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.TrafficManagerProfilesNestedEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -1592,6 +1667,110 @@ func (endpoint *TrafficManagerProfilesNestedEndpoint_STATUS) AssignProperties_To return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type TrafficManagerProfilesNestedEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec populates our TrafficManagerProfilesNestedEndpointOperatorSpec from the provided source TrafficManagerProfilesNestedEndpointOperatorSpec +func (operator *TrafficManagerProfilesNestedEndpointOperatorSpec) AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec(source *storage.TrafficManagerProfilesNestedEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec populates the provided destination TrafficManagerProfilesNestedEndpointOperatorSpec from our TrafficManagerProfilesNestedEndpointOperatorSpec +func (operator *TrafficManagerProfilesNestedEndpointOperatorSpec) AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec(destination *storage.TrafficManagerProfilesNestedEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&TrafficManagerProfilesNestedEndpoint{}, &TrafficManagerProfilesNestedEndpointList{}) } diff --git a/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen_test.go b/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen_test.go index 3bf28aa512c..559cb353a2a 100644 --- a/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220401/traffic_manager_profiles_nested_endpoint_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint(gens ma gens["Status"] = TrafficManagerProfilesNestedEndpoint_STATUSGenerator() } +func Test_TrafficManagerProfilesNestedEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from TrafficManagerProfilesNestedEndpointOperatorSpec to TrafficManagerProfilesNestedEndpointOperatorSpec via AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec & AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForTrafficManagerProfilesNestedEndpointOperatorSpec, TrafficManagerProfilesNestedEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForTrafficManagerProfilesNestedEndpointOperatorSpec tests if a specific instance of TrafficManagerProfilesNestedEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForTrafficManagerProfilesNestedEndpointOperatorSpec(subject TrafficManagerProfilesNestedEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.TrafficManagerProfilesNestedEndpointOperatorSpec + err := copied.AssignProperties_To_TrafficManagerProfilesNestedEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual TrafficManagerProfilesNestedEndpointOperatorSpec + err = actual.AssignProperties_From_TrafficManagerProfilesNestedEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_TrafficManagerProfilesNestedEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of TrafficManagerProfilesNestedEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec, TrafficManagerProfilesNestedEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec runs a test to see if a specific instance of TrafficManagerProfilesNestedEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForTrafficManagerProfilesNestedEndpointOperatorSpec(subject TrafficManagerProfilesNestedEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual TrafficManagerProfilesNestedEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of TrafficManagerProfilesNestedEndpointOperatorSpec instances for property testing - lazily instantiated by +// TrafficManagerProfilesNestedEndpointOperatorSpecGenerator() +var trafficManagerProfilesNestedEndpointOperatorSpecGenerator gopter.Gen + +// TrafficManagerProfilesNestedEndpointOperatorSpecGenerator returns a generator of TrafficManagerProfilesNestedEndpointOperatorSpec instances for property testing. +func TrafficManagerProfilesNestedEndpointOperatorSpecGenerator() gopter.Gen { + if trafficManagerProfilesNestedEndpointOperatorSpecGenerator != nil { + return trafficManagerProfilesNestedEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + trafficManagerProfilesNestedEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(TrafficManagerProfilesNestedEndpointOperatorSpec{}), generators) + + return trafficManagerProfilesNestedEndpointOperatorSpecGenerator +} + func Test_TrafficManagerProfilesNestedEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -438,5 +535,6 @@ func AddIndependentPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spe // AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForTrafficManagerProfilesNestedEndpoint_Spec(gens map[string]gopter.Gen) { gens["CustomHeaders"] = gen.SliceOf(EndpointProperties_CustomHeadersGenerator()) + gens["OperatorSpec"] = gen.PtrOf(TrafficManagerProfilesNestedEndpointOperatorSpecGenerator()) gens["Subnets"] = gen.SliceOf(EndpointProperties_SubnetsGenerator()) } diff --git a/v2/api/network/v1api20220401/zz_generated.deepcopy.go b/v2/api/network/v1api20220401/zz_generated.deepcopy.go index a2bfe083db6..90623a90896 100644 --- a/v2/api/network/v1api20220401/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20220401/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220401 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -510,11 +511,33 @@ func (in *TrafficManagerProfileOperatorConfigMaps) DeepCopy() *TrafficManagerPro // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfileOperatorSpec) DeepCopyInto(out *TrafficManagerProfileOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(TrafficManagerProfileOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfileOperatorSpec. @@ -754,6 +777,43 @@ func (in *TrafficManagerProfilesAzureEndpointList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesAzureEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesAzureEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesAzureEndpointOperatorSpec. +func (in *TrafficManagerProfilesAzureEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesAzureEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesAzureEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesAzureEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesAzureEndpoint_STATUS) { *out = *in @@ -915,6 +975,11 @@ func (in *TrafficManagerProfilesAzureEndpoint_Spec) DeepCopyInto(out *TrafficMan *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesAzureEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1023,6 +1088,43 @@ func (in *TrafficManagerProfilesExternalEndpointList) DeepCopyObject() runtime.O return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesExternalEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesExternalEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesExternalEndpointOperatorSpec. +func (in *TrafficManagerProfilesExternalEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesExternalEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesExternalEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesExternalEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesExternalEndpoint_STATUS) { *out = *in @@ -1184,6 +1286,11 @@ func (in *TrafficManagerProfilesExternalEndpoint_Spec) DeepCopyInto(out *Traffic *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesExternalEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1292,6 +1399,43 @@ func (in *TrafficManagerProfilesNestedEndpointList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficManagerProfilesNestedEndpointOperatorSpec) DeepCopyInto(out *TrafficManagerProfilesNestedEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficManagerProfilesNestedEndpointOperatorSpec. +func (in *TrafficManagerProfilesNestedEndpointOperatorSpec) DeepCopy() *TrafficManagerProfilesNestedEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(TrafficManagerProfilesNestedEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrafficManagerProfilesNestedEndpoint_STATUS) DeepCopyInto(out *TrafficManagerProfilesNestedEndpoint_STATUS) { *out = *in @@ -1453,6 +1597,11 @@ func (in *TrafficManagerProfilesNestedEndpoint_Spec) DeepCopyInto(out *TrafficMa *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(TrafficManagerProfilesNestedEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20220701/application_gateway_types_gen.go b/v2/api/network/v1api20220701/application_gateway_types_gen.go index 988f68b9f52..98c36a5a7b5 100644 --- a/v2/api/network/v1api20220701/application_gateway_types_gen.go +++ b/v2/api/network/v1api20220701/application_gateway_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (gateway *ApplicationGateway) defaultAzureName() { // defaultImpl applies the code generated defaults to the ApplicationGateway resource func (gateway *ApplicationGateway) defaultImpl() { gateway.defaultAzureName() } +var _ configmaps.Exporter = &ApplicationGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *ApplicationGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApplicationGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *ApplicationGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ApplicationGateway{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (gateway *ApplicationGateway) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (gateway *ApplicationGateway) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference} + return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference, gateway.validateSecretDestinations, gateway.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (gateway *ApplicationGateway) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return gateway.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (gateway *ApplicationGateway) validateConfigMapDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (gateway *ApplicationGateway) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (gateway *ApplicationGateway) validateSecretDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (gateway *ApplicationGateway) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ApplicationGateway) @@ -405,6 +450,10 @@ type ApplicationGateway_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApplicationGatewayOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1005,6 +1054,8 @@ func (gateway *ApplicationGateway_Spec) PopulateFromARM(owner genruntime.Arbitra gateway.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": gateway.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1542,6 +1593,18 @@ func (gateway *ApplicationGateway_Spec) AssignProperties_From_ApplicationGateway // Location gateway.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApplicationGatewayOperatorSpec + err := operatorSpec.AssignProperties_From_ApplicationGatewayOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApplicationGatewayOperatorSpec() to populate field OperatorSpec") + } + gateway.OperatorSpec = &operatorSpec + } else { + gateway.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -2075,6 +2138,18 @@ func (gateway *ApplicationGateway_Spec) AssignProperties_To_ApplicationGateway_S // Location destination.Location = genruntime.ClonePointerToString(gateway.Location) + // OperatorSpec + if gateway.OperatorSpec != nil { + var operatorSpec storage.ApplicationGatewayOperatorSpec + err := gateway.OperatorSpec.AssignProperties_To_ApplicationGatewayOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApplicationGatewayOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = gateway.OriginalVersion() @@ -8710,6 +8785,110 @@ func (policy *ApplicationGatewayLoadDistributionPolicy_STATUS) AssignProperties_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApplicationGatewayOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApplicationGatewayOperatorSpec populates our ApplicationGatewayOperatorSpec from the provided source ApplicationGatewayOperatorSpec +func (operator *ApplicationGatewayOperatorSpec) AssignProperties_From_ApplicationGatewayOperatorSpec(source *storage.ApplicationGatewayOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApplicationGatewayOperatorSpec populates the provided destination ApplicationGatewayOperatorSpec from our ApplicationGatewayOperatorSpec +func (operator *ApplicationGatewayOperatorSpec) AssignProperties_To_ApplicationGatewayOperatorSpec(destination *storage.ApplicationGatewayOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Private Endpoint connection on an application gateway. type ApplicationGatewayPrivateEndpointConnection_STATUS struct { // Id: Resource ID. diff --git a/v2/api/network/v1api20220701/application_gateway_types_gen_test.go b/v2/api/network/v1api20220701/application_gateway_types_gen_test.go index d7c09bfe66d..fe40d989457 100644 --- a/v2/api/network/v1api20220701/application_gateway_types_gen_test.go +++ b/v2/api/network/v1api20220701/application_gateway_types_gen_test.go @@ -3945,6 +3945,103 @@ func ApplicationGatewayLoadDistributionTargetGenerator() gopter.Gen { return applicationGatewayLoadDistributionTargetGenerator } +func Test_ApplicationGatewayOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApplicationGatewayOperatorSpec to ApplicationGatewayOperatorSpec via AssignProperties_To_ApplicationGatewayOperatorSpec & AssignProperties_From_ApplicationGatewayOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApplicationGatewayOperatorSpec, ApplicationGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApplicationGatewayOperatorSpec tests if a specific instance of ApplicationGatewayOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApplicationGatewayOperatorSpec(subject ApplicationGatewayOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApplicationGatewayOperatorSpec + err := copied.AssignProperties_To_ApplicationGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApplicationGatewayOperatorSpec + err = actual.AssignProperties_From_ApplicationGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApplicationGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApplicationGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApplicationGatewayOperatorSpec, ApplicationGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApplicationGatewayOperatorSpec runs a test to see if a specific instance of ApplicationGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApplicationGatewayOperatorSpec(subject ApplicationGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApplicationGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApplicationGatewayOperatorSpec instances for property testing - lazily instantiated by +// ApplicationGatewayOperatorSpecGenerator() +var applicationGatewayOperatorSpecGenerator gopter.Gen + +// ApplicationGatewayOperatorSpecGenerator returns a generator of ApplicationGatewayOperatorSpec instances for property testing. +func ApplicationGatewayOperatorSpecGenerator() gopter.Gen { + if applicationGatewayOperatorSpecGenerator != nil { + return applicationGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + applicationGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApplicationGatewayOperatorSpec{}), generators) + + return applicationGatewayOperatorSpecGenerator +} + func Test_ApplicationGatewayPathRule_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -8488,6 +8585,7 @@ func AddRelatedPropertyGeneratorsForApplicationGateway_Spec(gens map[string]gopt gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) gens["Listeners"] = gen.SliceOf(ApplicationGatewayListenerGenerator()) gens["LoadDistributionPolicies"] = gen.SliceOf(ApplicationGatewayLoadDistributionPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApplicationGatewayOperatorSpecGenerator()) gens["PrivateLinkConfigurations"] = gen.SliceOf(ApplicationGatewayPrivateLinkConfigurationGenerator()) gens["Probes"] = gen.SliceOf(ApplicationGatewayProbeGenerator()) gens["RedirectConfigurations"] = gen.SliceOf(ApplicationGatewayRedirectConfigurationGenerator()) diff --git a/v2/api/network/v1api20220701/bastion_host_types_gen.go b/v2/api/network/v1api20220701/bastion_host_types_gen.go index 5f5367e33a4..ffcaef27591 100644 --- a/v2/api/network/v1api20220701/bastion_host_types_gen.go +++ b/v2/api/network/v1api20220701/bastion_host_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (host *BastionHost) defaultAzureName() { // defaultImpl applies the code generated defaults to the BastionHost resource func (host *BastionHost) defaultImpl() { host.defaultAzureName() } +var _ configmaps.Exporter = &BastionHost{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (host *BastionHost) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if host.Spec.OperatorSpec == nil { + return nil + } + return host.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BastionHost{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (host *BastionHost) SecretDestinationExpressions() []*core.DestinationExpression { + if host.Spec.OperatorSpec == nil { + return nil + } + return host.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &BastionHost{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (host *BastionHost) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (host *BastionHost) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){host.validateResourceReferences, host.validateOwnerReference} + return []func() (admission.Warnings, error){host.validateResourceReferences, host.validateOwnerReference, host.validateSecretDestinations, host.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (host *BastionHost) updateValidations() []func(old runtime.Object) (admissi func(old runtime.Object) (admission.Warnings, error) { return host.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return host.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return host.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (host *BastionHost) validateConfigMapDestinations() (admission.Warnings, error) { + if host.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(host, nil, host.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (host *BastionHost) validateResourceReferences() (admission.Warnings, error return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (host *BastionHost) validateSecretDestinations() (admission.Warnings, error) { + if host.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(host, nil, host.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (host *BastionHost) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*BastionHost) @@ -354,6 +399,10 @@ type BastionHost_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BastionHostOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -545,6 +594,8 @@ func (host *BastionHost_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRef host.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": host.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -703,6 +754,18 @@ func (host *BastionHost_Spec) AssignProperties_From_BastionHost_Spec(source *sto // Location host.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BastionHostOperatorSpec + err := operatorSpec.AssignProperties_From_BastionHostOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BastionHostOperatorSpec() to populate field OperatorSpec") + } + host.OperatorSpec = &operatorSpec + } else { + host.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -810,6 +873,18 @@ func (host *BastionHost_Spec) AssignProperties_To_BastionHost_Spec(destination * // Location destination.Location = genruntime.ClonePointerToString(host.Location) + // OperatorSpec + if host.OperatorSpec != nil { + var operatorSpec storage.BastionHostOperatorSpec + err := host.OperatorSpec.AssignProperties_To_BastionHostOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BastionHostOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = host.OriginalVersion() @@ -1735,6 +1810,110 @@ func (configuration *BastionHostIPConfiguration_STATUS) AssignProperties_To_Bast return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BastionHostOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BastionHostOperatorSpec populates our BastionHostOperatorSpec from the provided source BastionHostOperatorSpec +func (operator *BastionHostOperatorSpec) AssignProperties_From_BastionHostOperatorSpec(source *storage.BastionHostOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BastionHostOperatorSpec populates the provided destination BastionHostOperatorSpec from our BastionHostOperatorSpec +func (operator *BastionHostOperatorSpec) AssignProperties_To_BastionHostOperatorSpec(destination *storage.BastionHostOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The current provisioning state. type BastionHostProvisioningState_STATUS string diff --git a/v2/api/network/v1api20220701/bastion_host_types_gen_test.go b/v2/api/network/v1api20220701/bastion_host_types_gen_test.go index a7281d116a1..30105fbaabb 100644 --- a/v2/api/network/v1api20220701/bastion_host_types_gen_test.go +++ b/v2/api/network/v1api20220701/bastion_host_types_gen_test.go @@ -386,6 +386,103 @@ func AddIndependentPropertyGeneratorsForBastionHostIPConfiguration_STATUS(gens m gens["Id"] = gen.PtrOf(gen.AlphaString()) } +func Test_BastionHostOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from BastionHostOperatorSpec to BastionHostOperatorSpec via AssignProperties_To_BastionHostOperatorSpec & AssignProperties_From_BastionHostOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForBastionHostOperatorSpec, BastionHostOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForBastionHostOperatorSpec tests if a specific instance of BastionHostOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForBastionHostOperatorSpec(subject BastionHostOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.BastionHostOperatorSpec + err := copied.AssignProperties_To_BastionHostOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual BastionHostOperatorSpec + err = actual.AssignProperties_From_BastionHostOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_BastionHostOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BastionHostOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBastionHostOperatorSpec, BastionHostOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBastionHostOperatorSpec runs a test to see if a specific instance of BastionHostOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBastionHostOperatorSpec(subject BastionHostOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BastionHostOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BastionHostOperatorSpec instances for property testing - lazily instantiated by +// BastionHostOperatorSpecGenerator() +var bastionHostOperatorSpecGenerator gopter.Gen + +// BastionHostOperatorSpecGenerator returns a generator of BastionHostOperatorSpec instances for property testing. +func BastionHostOperatorSpecGenerator() gopter.Gen { + if bastionHostOperatorSpecGenerator != nil { + return bastionHostOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + bastionHostOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BastionHostOperatorSpec{}), generators) + + return bastionHostOperatorSpecGenerator +} + func Test_BastionHostSubResource_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -744,6 +841,7 @@ func AddIndependentPropertyGeneratorsForBastionHost_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForBastionHost_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBastionHost_Spec(gens map[string]gopter.Gen) { gens["IpConfigurations"] = gen.SliceOf(BastionHostIPConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BastionHostOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen.go b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen.go index a8811851586..0795c486291 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen.go +++ b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (rule *DnsForwardingRuleSetsForwardingRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsForwardingRuleSetsForwardingRule resource func (rule *DnsForwardingRuleSetsForwardingRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &DnsForwardingRuleSetsForwardingRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *DnsForwardingRuleSetsForwardingRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleSetsForwardingRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *DnsForwardingRuleSetsForwardingRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsForwardingRuleSetsForwardingRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (rule *DnsForwardingRuleSetsForwardingRule) ValidateUpdate(old runtime.Obje // createValidations validates the creation of the resource func (rule *DnsForwardingRuleSetsForwardingRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations, rule.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (rule *DnsForwardingRuleSetsForwardingRule) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return rule.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *DnsForwardingRuleSetsForwardingRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (rule *DnsForwardingRuleSetsForwardingRule) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&rule.Spec) @@ -257,6 +293,14 @@ func (rule *DnsForwardingRuleSetsForwardingRule) validateResourceReferences() (a return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *DnsForwardingRuleSetsForwardingRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *DnsForwardingRuleSetsForwardingRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsForwardingRuleSetsForwardingRule) @@ -353,6 +397,10 @@ type DnsForwardingRuleSetsForwardingRule_Spec struct { // Metadata: Metadata attached to the forwarding rule. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsForwardingRuleSetsForwardingRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -455,6 +503,8 @@ func (rule *DnsForwardingRuleSetsForwardingRule_Spec) PopulateFromARM(owner genr } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -549,6 +599,18 @@ func (rule *DnsForwardingRuleSetsForwardingRule_Spec) AssignProperties_From_DnsF // Metadata rule.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsForwardingRuleSetsForwardingRuleOperatorSpec + err := operatorSpec.AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -601,6 +663,18 @@ func (rule *DnsForwardingRuleSetsForwardingRule_Spec) AssignProperties_To_DnsFor // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(rule.Metadata) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.DnsForwardingRuleSetsForwardingRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1046,6 +1120,110 @@ func (rule *DnsForwardingRuleSetsForwardingRule_STATUS) AssignProperties_To_DnsF return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRuleSetsForwardingRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec populates our DnsForwardingRuleSetsForwardingRuleOperatorSpec from the provided source DnsForwardingRuleSetsForwardingRuleOperatorSpec +func (operator *DnsForwardingRuleSetsForwardingRuleOperatorSpec) AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec(source *storage.DnsForwardingRuleSetsForwardingRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec populates the provided destination DnsForwardingRuleSetsForwardingRuleOperatorSpec from our DnsForwardingRuleSetsForwardingRuleOperatorSpec +func (operator *DnsForwardingRuleSetsForwardingRuleOperatorSpec) AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec(destination *storage.DnsForwardingRuleSetsForwardingRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The current provisioning state of the resource. type DnsresolverProvisioningState_STATUS string diff --git a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go index 35236f30ee5..3bf9ddc21b5 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule(gens map gens["Status"] = DnsForwardingRuleSetsForwardingRule_STATUSGenerator() } +func Test_DnsForwardingRuleSetsForwardingRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsForwardingRuleSetsForwardingRuleOperatorSpec to DnsForwardingRuleSetsForwardingRuleOperatorSpec via AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec & AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec, DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec tests if a specific instance of DnsForwardingRuleSetsForwardingRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec(subject DnsForwardingRuleSetsForwardingRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsForwardingRuleSetsForwardingRuleOperatorSpec + err := copied.AssignProperties_To_DnsForwardingRuleSetsForwardingRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsForwardingRuleSetsForwardingRuleOperatorSpec + err = actual.AssignProperties_From_DnsForwardingRuleSetsForwardingRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsForwardingRuleSetsForwardingRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRuleSetsForwardingRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec, DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec runs a test to see if a specific instance of DnsForwardingRuleSetsForwardingRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec(subject DnsForwardingRuleSetsForwardingRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRuleSetsForwardingRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRuleSetsForwardingRuleOperatorSpec instances for property testing - lazily instantiated by +// DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator() +var dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator gopter.Gen + +// DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator returns a generator of DnsForwardingRuleSetsForwardingRuleOperatorSpec instances for property testing. +func DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator != nil { + return dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRuleSetsForwardingRuleOperatorSpec{}), generators) + + return dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator +} + func Test_DnsForwardingRuleSetsForwardingRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -417,6 +514,7 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec // AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator()) gens["TargetDnsServers"] = gen.SliceOf(TargetDnsServerGenerator()) } diff --git a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen.go b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen.go index 867079892de..076b39f3676 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen.go +++ b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsForwardingRuleSetsVirtualNetworkLink resource func (link *DnsForwardingRuleSetsVirtualNetworkLink) defaultImpl() { link.defaultAzureName() } +var _ configmaps.Exporter = &DnsForwardingRuleSetsVirtualNetworkLink{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (link *DnsForwardingRuleSetsVirtualNetworkLink) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleSetsVirtualNetworkLink{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (link *DnsForwardingRuleSetsVirtualNetworkLink) SecretDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsForwardingRuleSetsVirtualNetworkLink{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink) ValidateUpdate(old runtime. // createValidations validates the creation of the resource func (link *DnsForwardingRuleSetsVirtualNetworkLink) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){link.validateResourceReferences, link.validateOwnerReference} + return []func() (admission.Warnings, error){link.validateResourceReferences, link.validateOwnerReference, link.validateSecretDestinations, link.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink) updateValidations() []func( func(old runtime.Object) (admission.Warnings, error) { return link.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return link.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return link.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (link *DnsForwardingRuleSetsVirtualNetworkLink) validateConfigMapDestinations() (admission.Warnings, error) { + if link.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(link, nil, link.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink) validateResourceReferences( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (link *DnsForwardingRuleSetsVirtualNetworkLink) validateSecretDestinations() (admission.Warnings, error) { + if link.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(link, nil, link.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (link *DnsForwardingRuleSetsVirtualNetworkLink) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsForwardingRuleSetsVirtualNetworkLink) @@ -333,6 +378,10 @@ type DnsForwardingRuleSetsVirtualNetworkLink_Spec struct { // Metadata: Metadata attached to the virtual network link. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -403,6 +452,8 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink_Spec) PopulateFromARM(owner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": link.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -486,6 +537,18 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink_Spec) AssignProperties_From_ // Metadata link.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err := operatorSpec.AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec() to populate field OperatorSpec") + } + link.OperatorSpec = &operatorSpec + } else { + link.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -521,6 +584,18 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink_Spec) AssignProperties_To_Dn // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(link.Metadata) + // OperatorSpec + if link.OperatorSpec != nil { + var operatorSpec storage.DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err := link.OperatorSpec.AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = link.OriginalVersion() @@ -883,6 +958,110 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) AssignProperties_To_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec populates our DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec from the provided source DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec +func (operator *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(source *storage.DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec populates the provided destination DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec from our DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec +func (operator *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(destination *storage.DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Reference to another ARM resource. type DnsresolverSubResource struct { // +kubebuilder:validation:Required diff --git a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go index 8d3644c62c3..c9efeb66eec 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink(gens gens["Status"] = DnsForwardingRuleSetsVirtualNetworkLink_STATUSGenerator() } +func Test_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec to DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec via AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec & AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec, DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec tests if a specific instance of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(subject DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err := copied.AssignProperties_To_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err = actual.AssignProperties_From_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec, DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec runs a test to see if a specific instance of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(subject DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec instances for property testing - lazily instantiated +// by DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator() +var dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator gopter.Gen + +// DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator returns a generator of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec instances for property testing. +func DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator != nil { + return dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec{}), generators) + + return dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator +} + func Test_DnsForwardingRuleSetsVirtualNetworkLink_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -413,6 +510,7 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_ // AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen.go b/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen.go index 37d675e76a2..e10a10ec6fa 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen.go +++ b/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (ruleset *DnsForwardingRuleset) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsForwardingRuleset resource func (ruleset *DnsForwardingRuleset) defaultImpl() { ruleset.defaultAzureName() } +var _ configmaps.Exporter = &DnsForwardingRuleset{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (ruleset *DnsForwardingRuleset) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if ruleset.Spec.OperatorSpec == nil { + return nil + } + return ruleset.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleset{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (ruleset *DnsForwardingRuleset) SecretDestinationExpressions() []*core.DestinationExpression { + if ruleset.Spec.OperatorSpec == nil { + return nil + } + return ruleset.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsForwardingRuleset{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (ruleset *DnsForwardingRuleset) ValidateUpdate(old runtime.Object) (admissi // createValidations validates the creation of the resource func (ruleset *DnsForwardingRuleset) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){ruleset.validateResourceReferences, ruleset.validateOwnerReference} + return []func() (admission.Warnings, error){ruleset.validateResourceReferences, ruleset.validateOwnerReference, ruleset.validateSecretDestinations, ruleset.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (ruleset *DnsForwardingRuleset) updateValidations() []func(old runtime.Obje func(old runtime.Object) (admission.Warnings, error) { return ruleset.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return ruleset.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return ruleset.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (ruleset *DnsForwardingRuleset) validateConfigMapDestinations() (admission.Warnings, error) { + if ruleset.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(ruleset, nil, ruleset.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (ruleset *DnsForwardingRuleset) validateResourceReferences() (admission.War return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (ruleset *DnsForwardingRuleset) validateSecretDestinations() (admission.Warnings, error) { + if ruleset.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(ruleset, nil, ruleset.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (ruleset *DnsForwardingRuleset) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsForwardingRuleset) @@ -339,6 +384,10 @@ type DnsForwardingRuleset_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsForwardingRulesetOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -423,6 +472,8 @@ func (ruleset *DnsForwardingRuleset_Spec) PopulateFromARM(owner genruntime.Arbit ruleset.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": ruleset.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -518,6 +569,18 @@ func (ruleset *DnsForwardingRuleset_Spec) AssignProperties_From_DnsForwardingRul // Location ruleset.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsForwardingRulesetOperatorSpec + err := operatorSpec.AssignProperties_From_DnsForwardingRulesetOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsForwardingRulesetOperatorSpec() to populate field OperatorSpec") + } + ruleset.OperatorSpec = &operatorSpec + } else { + ruleset.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -562,6 +625,18 @@ func (ruleset *DnsForwardingRuleset_Spec) AssignProperties_To_DnsForwardingRules // Location destination.Location = genruntime.ClonePointerToString(ruleset.Location) + // OperatorSpec + if ruleset.OperatorSpec != nil { + var operatorSpec storage.DnsForwardingRulesetOperatorSpec + err := ruleset.OperatorSpec.AssignProperties_To_DnsForwardingRulesetOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsForwardingRulesetOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = ruleset.OriginalVersion() @@ -967,6 +1042,110 @@ func (ruleset *DnsForwardingRuleset_STATUS) AssignProperties_To_DnsForwardingRul return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRulesetOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsForwardingRulesetOperatorSpec populates our DnsForwardingRulesetOperatorSpec from the provided source DnsForwardingRulesetOperatorSpec +func (operator *DnsForwardingRulesetOperatorSpec) AssignProperties_From_DnsForwardingRulesetOperatorSpec(source *storage.DnsForwardingRulesetOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsForwardingRulesetOperatorSpec populates the provided destination DnsForwardingRulesetOperatorSpec from our DnsForwardingRulesetOperatorSpec +func (operator *DnsForwardingRulesetOperatorSpec) AssignProperties_To_DnsForwardingRulesetOperatorSpec(destination *storage.DnsForwardingRulesetOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsForwardingRuleset{}, &DnsForwardingRulesetList{}) } diff --git a/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen_test.go b/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen_test.go index 67606f391c9..bea35c044d6 100644 --- a/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_forwarding_ruleset_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleset(gens map[string]gopter. gens["Status"] = DnsForwardingRuleset_STATUSGenerator() } +func Test_DnsForwardingRulesetOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsForwardingRulesetOperatorSpec to DnsForwardingRulesetOperatorSpec via AssignProperties_To_DnsForwardingRulesetOperatorSpec & AssignProperties_From_DnsForwardingRulesetOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsForwardingRulesetOperatorSpec, DnsForwardingRulesetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsForwardingRulesetOperatorSpec tests if a specific instance of DnsForwardingRulesetOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsForwardingRulesetOperatorSpec(subject DnsForwardingRulesetOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsForwardingRulesetOperatorSpec + err := copied.AssignProperties_To_DnsForwardingRulesetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsForwardingRulesetOperatorSpec + err = actual.AssignProperties_From_DnsForwardingRulesetOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsForwardingRulesetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRulesetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec, DnsForwardingRulesetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec runs a test to see if a specific instance of DnsForwardingRulesetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec(subject DnsForwardingRulesetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRulesetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRulesetOperatorSpec instances for property testing - lazily instantiated by +// DnsForwardingRulesetOperatorSpecGenerator() +var dnsForwardingRulesetOperatorSpecGenerator gopter.Gen + +// DnsForwardingRulesetOperatorSpecGenerator returns a generator of DnsForwardingRulesetOperatorSpec instances for property testing. +func DnsForwardingRulesetOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRulesetOperatorSpecGenerator != nil { + return dnsForwardingRulesetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRulesetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRulesetOperatorSpec{}), generators) + + return dnsForwardingRulesetOperatorSpecGenerator +} + func Test_DnsForwardingRuleset_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -417,4 +514,5 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleset_Spec(gens map[strin // AddRelatedPropertyGeneratorsForDnsForwardingRuleset_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleset_Spec(gens map[string]gopter.Gen) { gens["DnsResolverOutboundEndpoints"] = gen.SliceOf(DnsresolverSubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRulesetOperatorSpecGenerator()) } diff --git a/v2/api/network/v1api20220701/dns_resolver_types_gen.go b/v2/api/network/v1api20220701/dns_resolver_types_gen.go index 4e8a48a8588..871ea69e02f 100644 --- a/v2/api/network/v1api20220701/dns_resolver_types_gen.go +++ b/v2/api/network/v1api20220701/dns_resolver_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (resolver *DnsResolver) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsResolver resource func (resolver *DnsResolver) defaultImpl() { resolver.defaultAzureName() } +var _ configmaps.Exporter = &DnsResolver{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resolver *DnsResolver) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resolver.Spec.OperatorSpec == nil { + return nil + } + return resolver.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolver{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resolver *DnsResolver) SecretDestinationExpressions() []*core.DestinationExpression { + if resolver.Spec.OperatorSpec == nil { + return nil + } + return resolver.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsResolver{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (resolver *DnsResolver) ValidateUpdate(old runtime.Object) (admission.Warni // createValidations validates the creation of the resource func (resolver *DnsResolver) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resolver.validateResourceReferences, resolver.validateOwnerReference} + return []func() (admission.Warnings, error){resolver.validateResourceReferences, resolver.validateOwnerReference, resolver.validateSecretDestinations, resolver.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (resolver *DnsResolver) updateValidations() []func(old runtime.Object) (adm func(old runtime.Object) (admission.Warnings, error) { return resolver.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resolver.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resolver.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resolver *DnsResolver) validateConfigMapDestinations() (admission.Warnings, error) { + if resolver.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resolver, nil, resolver.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (resolver *DnsResolver) validateResourceReferences() (admission.Warnings, e return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resolver *DnsResolver) validateSecretDestinations() (admission.Warnings, error) { + if resolver.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resolver, nil, resolver.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resolver *DnsResolver) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsResolver) @@ -334,6 +379,10 @@ type DnsResolver_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsResolverOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -410,6 +459,8 @@ func (resolver *DnsResolver_Spec) PopulateFromARM(owner genruntime.ArbitraryOwne resolver.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": resolver.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -501,6 +552,18 @@ func (resolver *DnsResolver_Spec) AssignProperties_From_DnsResolver_Spec(source // Location resolver.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsResolverOperatorSpec + err := operatorSpec.AssignProperties_From_DnsResolverOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsResolverOperatorSpec() to populate field OperatorSpec") + } + resolver.OperatorSpec = &operatorSpec + } else { + resolver.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -539,6 +602,18 @@ func (resolver *DnsResolver_Spec) AssignProperties_To_DnsResolver_Spec(destinati // Location destination.Location = genruntime.ClonePointerToString(resolver.Location) + // OperatorSpec + if resolver.OperatorSpec != nil { + var operatorSpec storage.DnsResolverOperatorSpec + err := resolver.OperatorSpec.AssignProperties_To_DnsResolverOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsResolverOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resolver.OriginalVersion() @@ -968,6 +1043,110 @@ func (resolver *DnsResolver_STATUS) AssignProperties_To_DnsResolver_STATUS(desti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolverOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsResolverOperatorSpec populates our DnsResolverOperatorSpec from the provided source DnsResolverOperatorSpec +func (operator *DnsResolverOperatorSpec) AssignProperties_From_DnsResolverOperatorSpec(source *storage.DnsResolverOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsResolverOperatorSpec populates the provided destination DnsResolverOperatorSpec from our DnsResolverOperatorSpec +func (operator *DnsResolverOperatorSpec) AssignProperties_To_DnsResolverOperatorSpec(destination *storage.DnsResolverOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type DnsResolverProperties_DnsResolverState_STATUS string const ( diff --git a/v2/api/network/v1api20220701/dns_resolver_types_gen_test.go b/v2/api/network/v1api20220701/dns_resolver_types_gen_test.go index c4ce80764c8..39dcd55c2d7 100644 --- a/v2/api/network/v1api20220701/dns_resolver_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_resolver_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForDnsResolver(gens map[string]gopter.Gen) { gens["Status"] = DnsResolver_STATUSGenerator() } +func Test_DnsResolverOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsResolverOperatorSpec to DnsResolverOperatorSpec via AssignProperties_To_DnsResolverOperatorSpec & AssignProperties_From_DnsResolverOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsResolverOperatorSpec, DnsResolverOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsResolverOperatorSpec tests if a specific instance of DnsResolverOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsResolverOperatorSpec(subject DnsResolverOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsResolverOperatorSpec + err := copied.AssignProperties_To_DnsResolverOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsResolverOperatorSpec + err = actual.AssignProperties_From_DnsResolverOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsResolverOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolverOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolverOperatorSpec, DnsResolverOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolverOperatorSpec runs a test to see if a specific instance of DnsResolverOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolverOperatorSpec(subject DnsResolverOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolverOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolverOperatorSpec instances for property testing - lazily instantiated by +// DnsResolverOperatorSpecGenerator() +var dnsResolverOperatorSpecGenerator gopter.Gen + +// DnsResolverOperatorSpecGenerator returns a generator of DnsResolverOperatorSpec instances for property testing. +func DnsResolverOperatorSpecGenerator() gopter.Gen { + if dnsResolverOperatorSpecGenerator != nil { + return dnsResolverOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolverOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolverOperatorSpec{}), generators) + + return dnsResolverOperatorSpecGenerator +} + func Test_DnsResolver_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -414,5 +511,6 @@ func AddIndependentPropertyGeneratorsForDnsResolver_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForDnsResolver_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolver_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsResolverOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen.go b/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen.go index 9b62327ce1c..6852829450a 100644 --- a/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *DnsResolversInboundEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsResolversInboundEndpoint resource func (endpoint *DnsResolversInboundEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &DnsResolversInboundEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *DnsResolversInboundEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolversInboundEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *DnsResolversInboundEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsResolversInboundEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *DnsResolversInboundEndpoint) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (endpoint *DnsResolversInboundEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *DnsResolversInboundEndpoint) updateValidations() []func(old runt func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *DnsResolversInboundEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *DnsResolversInboundEndpoint) validateResourceReferences() (admis return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *DnsResolversInboundEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *DnsResolversInboundEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsResolversInboundEndpoint) @@ -338,6 +383,10 @@ type DnsResolversInboundEndpoint_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsResolversInboundEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -422,6 +471,8 @@ func (endpoint *DnsResolversInboundEndpoint_Spec) PopulateFromARM(owner genrunti endpoint.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -517,6 +568,18 @@ func (endpoint *DnsResolversInboundEndpoint_Spec) AssignProperties_From_DnsResol // Location endpoint.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsResolversInboundEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_DnsResolversInboundEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsResolversInboundEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -561,6 +624,18 @@ func (endpoint *DnsResolversInboundEndpoint_Spec) AssignProperties_To_DnsResolve // Location destination.Location = genruntime.ClonePointerToString(endpoint.Location) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.DnsResolversInboundEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_DnsResolversInboundEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsResolversInboundEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -964,6 +1039,110 @@ func (endpoint *DnsResolversInboundEndpoint_STATUS) AssignProperties_To_DnsResol return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolversInboundEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsResolversInboundEndpointOperatorSpec populates our DnsResolversInboundEndpointOperatorSpec from the provided source DnsResolversInboundEndpointOperatorSpec +func (operator *DnsResolversInboundEndpointOperatorSpec) AssignProperties_From_DnsResolversInboundEndpointOperatorSpec(source *storage.DnsResolversInboundEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsResolversInboundEndpointOperatorSpec populates the provided destination DnsResolversInboundEndpointOperatorSpec from our DnsResolversInboundEndpointOperatorSpec +func (operator *DnsResolversInboundEndpointOperatorSpec) AssignProperties_To_DnsResolversInboundEndpointOperatorSpec(destination *storage.DnsResolversInboundEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // IP configuration. type IpConfiguration struct { // PrivateIpAddress: Private IP address of the IP configuration. diff --git a/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen_test.go b/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen_test.go index 756ee23dcaf..7053834eddd 100644 --- a/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_resolvers_inbound_endpoint_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint(gens map[string] gens["Status"] = DnsResolversInboundEndpoint_STATUSGenerator() } +func Test_DnsResolversInboundEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsResolversInboundEndpointOperatorSpec to DnsResolversInboundEndpointOperatorSpec via AssignProperties_To_DnsResolversInboundEndpointOperatorSpec & AssignProperties_From_DnsResolversInboundEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsResolversInboundEndpointOperatorSpec, DnsResolversInboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsResolversInboundEndpointOperatorSpec tests if a specific instance of DnsResolversInboundEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsResolversInboundEndpointOperatorSpec(subject DnsResolversInboundEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsResolversInboundEndpointOperatorSpec + err := copied.AssignProperties_To_DnsResolversInboundEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsResolversInboundEndpointOperatorSpec + err = actual.AssignProperties_From_DnsResolversInboundEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsResolversInboundEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolversInboundEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec, DnsResolversInboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec runs a test to see if a specific instance of DnsResolversInboundEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec(subject DnsResolversInboundEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolversInboundEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolversInboundEndpointOperatorSpec instances for property testing - lazily instantiated by +// DnsResolversInboundEndpointOperatorSpecGenerator() +var dnsResolversInboundEndpointOperatorSpecGenerator gopter.Gen + +// DnsResolversInboundEndpointOperatorSpecGenerator returns a generator of DnsResolversInboundEndpointOperatorSpec instances for property testing. +func DnsResolversInboundEndpointOperatorSpecGenerator() gopter.Gen { + if dnsResolversInboundEndpointOperatorSpecGenerator != nil { + return dnsResolversInboundEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolversInboundEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolversInboundEndpointOperatorSpec{}), generators) + + return dnsResolversInboundEndpointOperatorSpecGenerator +} + func Test_DnsResolversInboundEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -417,6 +514,7 @@ func AddIndependentPropertyGeneratorsForDnsResolversInboundEndpoint_Spec(gens ma // AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint_Spec(gens map[string]gopter.Gen) { gens["IpConfigurations"] = gen.SliceOf(IpConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsResolversInboundEndpointOperatorSpecGenerator()) } func Test_IpConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen.go b/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen.go index 6b23240690c..a645376959f 100644 --- a/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (endpoint *DnsResolversOutboundEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the DnsResolversOutboundEndpoint resource func (endpoint *DnsResolversOutboundEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &DnsResolversOutboundEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *DnsResolversOutboundEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolversOutboundEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *DnsResolversOutboundEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &DnsResolversOutboundEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (endpoint *DnsResolversOutboundEndpoint) ValidateUpdate(old runtime.Object) // createValidations validates the creation of the resource func (endpoint *DnsResolversOutboundEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (endpoint *DnsResolversOutboundEndpoint) updateValidations() []func(old run func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (endpoint *DnsResolversOutboundEndpoint) validateConfigMapDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (endpoint *DnsResolversOutboundEndpoint) validateResourceReferences() (admi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *DnsResolversOutboundEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *DnsResolversOutboundEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*DnsResolversOutboundEndpoint) @@ -334,6 +379,10 @@ type DnsResolversOutboundEndpoint_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DnsResolversOutboundEndpointOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -410,6 +459,8 @@ func (endpoint *DnsResolversOutboundEndpoint_Spec) PopulateFromARM(owner genrunt endpoint.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": endpoint.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -501,6 +552,18 @@ func (endpoint *DnsResolversOutboundEndpoint_Spec) AssignProperties_From_DnsReso // Location endpoint.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DnsResolversOutboundEndpointOperatorSpec + err := operatorSpec.AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec() to populate field OperatorSpec") + } + endpoint.OperatorSpec = &operatorSpec + } else { + endpoint.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -539,6 +602,18 @@ func (endpoint *DnsResolversOutboundEndpoint_Spec) AssignProperties_To_DnsResolv // Location destination.Location = genruntime.ClonePointerToString(endpoint.Location) + // OperatorSpec + if endpoint.OperatorSpec != nil { + var operatorSpec storage.DnsResolversOutboundEndpointOperatorSpec + err := endpoint.OperatorSpec.AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = endpoint.OriginalVersion() @@ -937,6 +1012,110 @@ func (endpoint *DnsResolversOutboundEndpoint_STATUS) AssignProperties_To_DnsReso return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolversOutboundEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec populates our DnsResolversOutboundEndpointOperatorSpec from the provided source DnsResolversOutboundEndpointOperatorSpec +func (operator *DnsResolversOutboundEndpointOperatorSpec) AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec(source *storage.DnsResolversOutboundEndpointOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec populates the provided destination DnsResolversOutboundEndpointOperatorSpec from our DnsResolversOutboundEndpointOperatorSpec +func (operator *DnsResolversOutboundEndpointOperatorSpec) AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec(destination *storage.DnsResolversOutboundEndpointOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&DnsResolversOutboundEndpoint{}, &DnsResolversOutboundEndpointList{}) } diff --git a/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen_test.go b/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen_test.go index f77c2fae9af..a572ffa866c 100644 --- a/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220701/dns_resolvers_outbound_endpoint_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint(gens map[string gens["Status"] = DnsResolversOutboundEndpoint_STATUSGenerator() } +func Test_DnsResolversOutboundEndpointOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from DnsResolversOutboundEndpointOperatorSpec to DnsResolversOutboundEndpointOperatorSpec via AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec & AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForDnsResolversOutboundEndpointOperatorSpec, DnsResolversOutboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForDnsResolversOutboundEndpointOperatorSpec tests if a specific instance of DnsResolversOutboundEndpointOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForDnsResolversOutboundEndpointOperatorSpec(subject DnsResolversOutboundEndpointOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.DnsResolversOutboundEndpointOperatorSpec + err := copied.AssignProperties_To_DnsResolversOutboundEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual DnsResolversOutboundEndpointOperatorSpec + err = actual.AssignProperties_From_DnsResolversOutboundEndpointOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_DnsResolversOutboundEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolversOutboundEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec, DnsResolversOutboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec runs a test to see if a specific instance of DnsResolversOutboundEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec(subject DnsResolversOutboundEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolversOutboundEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolversOutboundEndpointOperatorSpec instances for property testing - lazily instantiated by +// DnsResolversOutboundEndpointOperatorSpecGenerator() +var dnsResolversOutboundEndpointOperatorSpecGenerator gopter.Gen + +// DnsResolversOutboundEndpointOperatorSpecGenerator returns a generator of DnsResolversOutboundEndpointOperatorSpec instances for property testing. +func DnsResolversOutboundEndpointOperatorSpecGenerator() gopter.Gen { + if dnsResolversOutboundEndpointOperatorSpecGenerator != nil { + return dnsResolversOutboundEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolversOutboundEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolversOutboundEndpointOperatorSpec{}), generators) + + return dnsResolversOutboundEndpointOperatorSpecGenerator +} + func Test_DnsResolversOutboundEndpoint_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -416,5 +513,6 @@ func AddIndependentPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec(gens m // AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsResolversOutboundEndpointOperatorSpecGenerator()) gens["Subnet"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/nat_gateway_types_gen.go b/v2/api/network/v1api20220701/nat_gateway_types_gen.go index ea76a98c04a..0951e0ec017 100644 --- a/v2/api/network/v1api20220701/nat_gateway_types_gen.go +++ b/v2/api/network/v1api20220701/nat_gateway_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (gateway *NatGateway) defaultAzureName() { // defaultImpl applies the code generated defaults to the NatGateway resource func (gateway *NatGateway) defaultImpl() { gateway.defaultAzureName() } +var _ configmaps.Exporter = &NatGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *NatGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NatGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *NatGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NatGateway{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (gateway *NatGateway) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (gateway *NatGateway) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference} + return []func() (admission.Warnings, error){gateway.validateResourceReferences, gateway.validateOwnerReference, gateway.validateSecretDestinations, gateway.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (gateway *NatGateway) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return gateway.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return gateway.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (gateway *NatGateway) validateConfigMapDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (gateway *NatGateway) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (gateway *NatGateway) validateSecretDestinations() (admission.Warnings, error) { + if gateway.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(gateway, nil, gateway.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (gateway *NatGateway) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NatGateway) @@ -336,6 +381,10 @@ type NatGateway_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NatGatewayOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -456,6 +505,8 @@ func (gateway *NatGateway_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR gateway.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": gateway.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -578,6 +629,18 @@ func (gateway *NatGateway_Spec) AssignProperties_From_NatGateway_Spec(source *st // Location gateway.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NatGatewayOperatorSpec + err := operatorSpec.AssignProperties_From_NatGatewayOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NatGatewayOperatorSpec() to populate field OperatorSpec") + } + gateway.OperatorSpec = &operatorSpec + } else { + gateway.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -658,6 +721,18 @@ func (gateway *NatGateway_Spec) AssignProperties_To_NatGateway_Spec(destination // Location destination.Location = genruntime.ClonePointerToString(gateway.Location) + // OperatorSpec + if gateway.OperatorSpec != nil { + var operatorSpec storage.NatGatewayOperatorSpec + err := gateway.OperatorSpec.AssignProperties_To_NatGatewayOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NatGatewayOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = gateway.OriginalVersion() @@ -1281,6 +1356,110 @@ func (gateway *NatGateway_STATUS) AssignProperties_To_NatGateway_STATUS(destinat return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NatGatewayOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NatGatewayOperatorSpec populates our NatGatewayOperatorSpec from the provided source NatGatewayOperatorSpec +func (operator *NatGatewayOperatorSpec) AssignProperties_From_NatGatewayOperatorSpec(source *storage.NatGatewayOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NatGatewayOperatorSpec populates the provided destination NatGatewayOperatorSpec from our NatGatewayOperatorSpec +func (operator *NatGatewayOperatorSpec) AssignProperties_To_NatGatewayOperatorSpec(destination *storage.NatGatewayOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // SKU of nat gateway. type NatGatewaySku struct { // Name: Name of Nat Gateway SKU. diff --git a/v2/api/network/v1api20220701/nat_gateway_types_gen_test.go b/v2/api/network/v1api20220701/nat_gateway_types_gen_test.go index e9d94588d04..c4161794fcc 100644 --- a/v2/api/network/v1api20220701/nat_gateway_types_gen_test.go +++ b/v2/api/network/v1api20220701/nat_gateway_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForNatGateway(gens map[string]gopter.Gen) { gens["Status"] = NatGateway_STATUSGenerator() } +func Test_NatGatewayOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NatGatewayOperatorSpec to NatGatewayOperatorSpec via AssignProperties_To_NatGatewayOperatorSpec & AssignProperties_From_NatGatewayOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNatGatewayOperatorSpec, NatGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNatGatewayOperatorSpec tests if a specific instance of NatGatewayOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNatGatewayOperatorSpec(subject NatGatewayOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NatGatewayOperatorSpec + err := copied.AssignProperties_To_NatGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NatGatewayOperatorSpec + err = actual.AssignProperties_From_NatGatewayOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NatGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NatGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNatGatewayOperatorSpec, NatGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNatGatewayOperatorSpec runs a test to see if a specific instance of NatGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNatGatewayOperatorSpec(subject NatGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NatGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NatGatewayOperatorSpec instances for property testing - lazily instantiated by +// NatGatewayOperatorSpecGenerator() +var natGatewayOperatorSpecGenerator gopter.Gen + +// NatGatewayOperatorSpecGenerator returns a generator of NatGatewayOperatorSpec instances for property testing. +func NatGatewayOperatorSpecGenerator() gopter.Gen { + if natGatewayOperatorSpecGenerator != nil { + return natGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + natGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NatGatewayOperatorSpec{}), generators) + + return natGatewayOperatorSpecGenerator +} + func Test_NatGatewaySku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -622,6 +719,7 @@ func AddIndependentPropertyGeneratorsForNatGateway_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNatGateway_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNatGateway_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NatGatewayOperatorSpecGenerator()) gens["PublicIpAddresses"] = gen.SliceOf(ApplicationGatewaySubResourceGenerator()) gens["PublicIpPrefixes"] = gen.SliceOf(ApplicationGatewaySubResourceGenerator()) gens["Sku"] = gen.PtrOf(NatGatewaySkuGenerator()) diff --git a/v2/api/network/v1api20220701/private_endpoint_types_gen.go b/v2/api/network/v1api20220701/private_endpoint_types_gen.go index f0312b98631..116a53f10e7 100644 --- a/v2/api/network/v1api20220701/private_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/private_endpoint_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (endpoint *PrivateEndpoint) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateEndpoint resource func (endpoint *PrivateEndpoint) defaultImpl() { endpoint.defaultAzureName() } +var _ configmaps.Exporter = &PrivateEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *PrivateEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *PrivateEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateEndpoint{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (endpoint *PrivateEndpoint) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (endpoint *PrivateEndpoint) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateConfigMapDestinations} + return []func() (admission.Warnings, error){endpoint.validateResourceReferences, endpoint.validateOwnerReference, endpoint.validateSecretDestinations, endpoint.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -228,6 +250,9 @@ func (endpoint *PrivateEndpoint) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return endpoint.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return endpoint.validateConfigMapDestinations() }, @@ -239,13 +264,13 @@ func (endpoint *PrivateEndpoint) validateConfigMapDestinations() (admission.Warn if endpoint.Spec.OperatorSpec == nil { return nil, nil } - if endpoint.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - endpoint.Spec.OperatorSpec.ConfigMaps.PrimaryNicPrivateIpAddress, + var toValidate []*genruntime.ConfigMapDestination + if endpoint.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + endpoint.Spec.OperatorSpec.ConfigMaps.PrimaryNicPrivateIpAddress, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(endpoint, toValidate, endpoint.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -262,6 +287,14 @@ func (endpoint *PrivateEndpoint) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (endpoint *PrivateEndpoint) validateSecretDestinations() (admission.Warnings, error) { + if endpoint.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(endpoint, nil, endpoint.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (endpoint *PrivateEndpoint) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateEndpoint) @@ -2510,13 +2543,37 @@ func (configuration *PrivateEndpointIPConfiguration_STATUS) AssignProperties_To_ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PrivateEndpointOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *PrivateEndpointOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_PrivateEndpointOperatorSpec populates our PrivateEndpointOperatorSpec from the provided source PrivateEndpointOperatorSpec func (operator *PrivateEndpointOperatorSpec) AssignProperties_From_PrivateEndpointOperatorSpec(source *storage.PrivateEndpointOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap PrivateEndpointOperatorConfigMaps @@ -2529,6 +2586,24 @@ func (operator *PrivateEndpointOperatorSpec) AssignProperties_From_PrivateEndpoi operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2538,6 +2613,24 @@ func (operator *PrivateEndpointOperatorSpec) AssignProperties_To_PrivateEndpoint // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.PrivateEndpointOperatorConfigMaps @@ -2550,6 +2643,24 @@ func (operator *PrivateEndpointOperatorSpec) AssignProperties_To_PrivateEndpoint destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen.go b/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen.go index 9172a3025c9..8c7c07349bf 100644 --- a/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen.go +++ b/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateEndpointsPrivateDnsZoneGroup resource func (group *PrivateEndpointsPrivateDnsZoneGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &PrivateEndpointsPrivateDnsZoneGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *PrivateEndpointsPrivateDnsZoneGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateEndpointsPrivateDnsZoneGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *PrivateEndpointsPrivateDnsZoneGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateEndpointsPrivateDnsZoneGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (group *PrivateEndpointsPrivateDnsZoneGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *PrivateEndpointsPrivateDnsZoneGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup) validateResourceReferences() ( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *PrivateEndpointsPrivateDnsZoneGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *PrivateEndpointsPrivateDnsZoneGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateEndpointsPrivateDnsZoneGroup) @@ -330,6 +375,10 @@ type PrivateEndpointsPrivateDnsZoneGroup_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -381,6 +430,8 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup_Spec) PopulateFromARM(owner gen // Set property "AzureName": group.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -460,6 +511,18 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup_Spec) AssignProperties_From_Pri // AzureName group.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err := operatorSpec.AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -498,6 +561,18 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup_Spec) AssignProperties_To_Priva // AzureName destination.AzureName = group.AzureName + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -1078,6 +1153,110 @@ var privateEndpointProvisioningState_STATUS_Values = map[string]PrivateEndpointP "updating": PrivateEndpointProvisioningState_STATUS_Updating, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateEndpointsPrivateDnsZoneGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec populates our PrivateEndpointsPrivateDnsZoneGroupOperatorSpec from the provided source PrivateEndpointsPrivateDnsZoneGroupOperatorSpec +func (operator *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(source *storage.PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec populates the provided destination PrivateEndpointsPrivateDnsZoneGroupOperatorSpec from our PrivateEndpointsPrivateDnsZoneGroupOperatorSpec +func (operator *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(destination *storage.PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // A collective group of information about the record set information. type RecordSet_STATUS struct { // Fqdn: Fqdn that resolves to private endpoint ip address. diff --git a/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen_test.go b/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen_test.go index 3095f0184e6..115771d4f4b 100644 --- a/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen_test.go +++ b/v2/api/network/v1api20220701/private_endpoints_private_dns_zone_group_types_gen_test.go @@ -386,6 +386,103 @@ func AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup(gens map gens["Status"] = PrivateEndpointsPrivateDnsZoneGroup_STATUSGenerator() } +func Test_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PrivateEndpointsPrivateDnsZoneGroupOperatorSpec to PrivateEndpointsPrivateDnsZoneGroupOperatorSpec via AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec & AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec, PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec tests if a specific instance of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec(subject PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err := copied.AssignProperties_To_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err = actual.AssignProperties_From_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec, PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec runs a test to see if a specific instance of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec(subject PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec instances for property testing - lazily instantiated by +// PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator() +var privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator gopter.Gen + +// PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator returns a generator of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec instances for property testing. +func PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator() gopter.Gen { + if privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator != nil { + return privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec{}), generators) + + return privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator +} + func Test_PrivateEndpointsPrivateDnsZoneGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -624,6 +721,7 @@ func AddIndependentPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec // AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator()) gens["PrivateDnsZoneConfigs"] = gen.SliceOf(PrivateDnsZoneConfigGenerator()) } diff --git a/v2/api/network/v1api20220701/private_link_service_types_gen.go b/v2/api/network/v1api20220701/private_link_service_types_gen.go index 80193ab668b..a17520a6919 100644 --- a/v2/api/network/v1api20220701/private_link_service_types_gen.go +++ b/v2/api/network/v1api20220701/private_link_service_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (service *PrivateLinkService) defaultAzureName() { // defaultImpl applies the code generated defaults to the PrivateLinkService resource func (service *PrivateLinkService) defaultImpl() { service.defaultAzureName() } +var _ configmaps.Exporter = &PrivateLinkService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *PrivateLinkService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateLinkService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *PrivateLinkService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PrivateLinkService{} // InitializeSpec initializes the spec for this resource from the given status @@ -231,7 +253,7 @@ func (service *PrivateLinkService) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (service *PrivateLinkService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateConfigMapDestinations} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -249,6 +271,9 @@ func (service *PrivateLinkService) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return service.validateConfigMapDestinations() }, @@ -260,13 +285,13 @@ func (service *PrivateLinkService) validateConfigMapDestinations() (admission.Wa if service.Spec.OperatorSpec == nil { return nil, nil } - if service.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - service.Spec.OperatorSpec.ConfigMaps.Alias, + var toValidate []*genruntime.ConfigMapDestination + if service.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + service.Spec.OperatorSpec.ConfigMaps.Alias, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(service, toValidate, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -283,6 +308,14 @@ func (service *PrivateLinkService) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *PrivateLinkService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *PrivateLinkService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PrivateLinkService) @@ -2509,13 +2542,37 @@ func (configuration *PrivateLinkServiceIpConfiguration_STATUS) AssignProperties_ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PrivateLinkServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *PrivateLinkServiceOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_PrivateLinkServiceOperatorSpec populates our PrivateLinkServiceOperatorSpec from the provided source PrivateLinkServiceOperatorSpec func (operator *PrivateLinkServiceOperatorSpec) AssignProperties_From_PrivateLinkServiceOperatorSpec(source *storage.PrivateLinkServiceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap PrivateLinkServiceOperatorConfigMaps @@ -2528,6 +2585,24 @@ func (operator *PrivateLinkServiceOperatorSpec) AssignProperties_From_PrivateLin operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2537,6 +2612,24 @@ func (operator *PrivateLinkServiceOperatorSpec) AssignProperties_To_PrivateLinkS // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.PrivateLinkServiceOperatorConfigMaps @@ -2549,6 +2642,24 @@ func (operator *PrivateLinkServiceOperatorSpec) AssignProperties_To_PrivateLinkS destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/network/v1api20220701/public_ip_prefix_types_gen.go b/v2/api/network/v1api20220701/public_ip_prefix_types_gen.go index 4a3c0997571..307ea09089e 100644 --- a/v2/api/network/v1api20220701/public_ip_prefix_types_gen.go +++ b/v2/api/network/v1api20220701/public_ip_prefix_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (prefix *PublicIPPrefix) defaultAzureName() { // defaultImpl applies the code generated defaults to the PublicIPPrefix resource func (prefix *PublicIPPrefix) defaultImpl() { prefix.defaultAzureName() } +var _ configmaps.Exporter = &PublicIPPrefix{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (prefix *PublicIPPrefix) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if prefix.Spec.OperatorSpec == nil { + return nil + } + return prefix.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PublicIPPrefix{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (prefix *PublicIPPrefix) SecretDestinationExpressions() []*core.DestinationExpression { + if prefix.Spec.OperatorSpec == nil { + return nil + } + return prefix.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &PublicIPPrefix{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (prefix *PublicIPPrefix) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (prefix *PublicIPPrefix) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){prefix.validateResourceReferences, prefix.validateOwnerReference} + return []func() (admission.Warnings, error){prefix.validateResourceReferences, prefix.validateOwnerReference, prefix.validateSecretDestinations, prefix.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (prefix *PublicIPPrefix) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return prefix.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return prefix.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return prefix.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (prefix *PublicIPPrefix) validateConfigMapDestinations() (admission.Warnings, error) { + if prefix.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(prefix, nil, prefix.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (prefix *PublicIPPrefix) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (prefix *PublicIPPrefix) validateSecretDestinations() (admission.Warnings, error) { + if prefix.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(prefix, nil, prefix.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (prefix *PublicIPPrefix) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*PublicIPPrefix) @@ -345,6 +390,10 @@ type PublicIPPrefix_Spec struct { // NatGateway: NatGateway of Public IP Prefix. NatGateway *NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded `json:"natGateway,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *PublicIPPrefixOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -535,6 +584,8 @@ func (prefix *PublicIPPrefix_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": prefix.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -702,6 +753,18 @@ func (prefix *PublicIPPrefix_Spec) AssignProperties_From_PublicIPPrefix_Spec(sou prefix.NatGateway = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec PublicIPPrefixOperatorSpec + err := operatorSpec.AssignProperties_From_PublicIPPrefixOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_PublicIPPrefixOperatorSpec() to populate field OperatorSpec") + } + prefix.OperatorSpec = &operatorSpec + } else { + prefix.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -809,6 +872,18 @@ func (prefix *PublicIPPrefix_Spec) AssignProperties_To_PublicIPPrefix_Spec(desti destination.NatGateway = nil } + // OperatorSpec + if prefix.OperatorSpec != nil { + var operatorSpec storage.PublicIPPrefixOperatorSpec + err := prefix.OperatorSpec.AssignProperties_To_PublicIPPrefixOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_PublicIPPrefixOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = prefix.OriginalVersion() @@ -1961,6 +2036,110 @@ func (embedded *NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded) Initialize_Fr return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PublicIPPrefixOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_PublicIPPrefixOperatorSpec populates our PublicIPPrefixOperatorSpec from the provided source PublicIPPrefixOperatorSpec +func (operator *PublicIPPrefixOperatorSpec) AssignProperties_From_PublicIPPrefixOperatorSpec(source *storage.PublicIPPrefixOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_PublicIPPrefixOperatorSpec populates the provided destination PublicIPPrefixOperatorSpec from our PublicIPPrefixOperatorSpec +func (operator *PublicIPPrefixOperatorSpec) AssignProperties_To_PublicIPPrefixOperatorSpec(destination *storage.PublicIPPrefixOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The current provisioning state. type PublicIpPrefixProvisioningState_STATUS string diff --git a/v2/api/network/v1api20220701/public_ip_prefix_types_gen_test.go b/v2/api/network/v1api20220701/public_ip_prefix_types_gen_test.go index d9cb7fa231e..6bc4a139205 100644 --- a/v2/api/network/v1api20220701/public_ip_prefix_types_gen_test.go +++ b/v2/api/network/v1api20220701/public_ip_prefix_types_gen_test.go @@ -570,6 +570,103 @@ func AddRelatedPropertyGeneratorsForPublicIPPrefix(gens map[string]gopter.Gen) { gens["Status"] = PublicIPPrefix_STATUSGenerator() } +func Test_PublicIPPrefixOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from PublicIPPrefixOperatorSpec to PublicIPPrefixOperatorSpec via AssignProperties_To_PublicIPPrefixOperatorSpec & AssignProperties_From_PublicIPPrefixOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForPublicIPPrefixOperatorSpec, PublicIPPrefixOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForPublicIPPrefixOperatorSpec tests if a specific instance of PublicIPPrefixOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForPublicIPPrefixOperatorSpec(subject PublicIPPrefixOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.PublicIPPrefixOperatorSpec + err := copied.AssignProperties_To_PublicIPPrefixOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual PublicIPPrefixOperatorSpec + err = actual.AssignProperties_From_PublicIPPrefixOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_PublicIPPrefixOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PublicIPPrefixOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPublicIPPrefixOperatorSpec, PublicIPPrefixOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPublicIPPrefixOperatorSpec runs a test to see if a specific instance of PublicIPPrefixOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPublicIPPrefixOperatorSpec(subject PublicIPPrefixOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PublicIPPrefixOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PublicIPPrefixOperatorSpec instances for property testing - lazily instantiated by +// PublicIPPrefixOperatorSpecGenerator() +var publicIPPrefixOperatorSpecGenerator gopter.Gen + +// PublicIPPrefixOperatorSpecGenerator returns a generator of PublicIPPrefixOperatorSpec instances for property testing. +func PublicIPPrefixOperatorSpecGenerator() gopter.Gen { + if publicIPPrefixOperatorSpecGenerator != nil { + return publicIPPrefixOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + publicIPPrefixOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PublicIPPrefixOperatorSpec{}), generators) + + return publicIPPrefixOperatorSpecGenerator +} + func Test_PublicIPPrefixSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1042,6 +1139,7 @@ func AddRelatedPropertyGeneratorsForPublicIPPrefix_Spec(gens map[string]gopter.G gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpTags"] = gen.SliceOf(IpTagGenerator()) gens["NatGateway"] = gen.PtrOf(NatGatewaySpec_PublicIPPrefix_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PublicIPPrefixOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(PublicIPPrefixSkuGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/application_gateway_types_gen.go b/v2/api/network/v1api20220701/storage/application_gateway_types_gen.go index fd484a6ead9..bcdeb90f501 100644 --- a/v2/api/network/v1api20220701/storage/application_gateway_types_gen.go +++ b/v2/api/network/v1api20220701/storage/application_gateway_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (gateway *ApplicationGateway) SetConditions(conditions conditions.Condition gateway.Status.Conditions = conditions } +var _ configmaps.Exporter = &ApplicationGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *ApplicationGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApplicationGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *ApplicationGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ApplicationGateway{} // AzureName returns the Azure name of the resource @@ -169,6 +192,7 @@ type ApplicationGateway_Spec struct { Listeners []ApplicationGatewayListener `json:"listeners,omitempty"` LoadDistributionPolicies []ApplicationGatewayLoadDistributionPolicy `json:"loadDistributionPolicies,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *ApplicationGatewayOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -519,6 +543,14 @@ type ApplicationGatewayLoadDistributionPolicy_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220701.ApplicationGatewayOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApplicationGatewayOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.ApplicationGatewayPrivateEndpointConnection_STATUS // Private Endpoint connection on an application gateway. type ApplicationGatewayPrivateEndpointConnection_STATUS struct { diff --git a/v2/api/network/v1api20220701/storage/application_gateway_types_gen_test.go b/v2/api/network/v1api20220701/storage/application_gateway_types_gen_test.go index af71b34206a..a7c47977ef6 100644 --- a/v2/api/network/v1api20220701/storage/application_gateway_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/application_gateway_types_gen_test.go @@ -2373,6 +2373,61 @@ func ApplicationGatewayLoadDistributionTargetGenerator() gopter.Gen { return applicationGatewayLoadDistributionTargetGenerator } +func Test_ApplicationGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApplicationGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApplicationGatewayOperatorSpec, ApplicationGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApplicationGatewayOperatorSpec runs a test to see if a specific instance of ApplicationGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApplicationGatewayOperatorSpec(subject ApplicationGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApplicationGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApplicationGatewayOperatorSpec instances for property testing - lazily instantiated by +// ApplicationGatewayOperatorSpecGenerator() +var applicationGatewayOperatorSpecGenerator gopter.Gen + +// ApplicationGatewayOperatorSpecGenerator returns a generator of ApplicationGatewayOperatorSpec instances for property testing. +func ApplicationGatewayOperatorSpecGenerator() gopter.Gen { + if applicationGatewayOperatorSpecGenerator != nil { + return applicationGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + applicationGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApplicationGatewayOperatorSpec{}), generators) + + return applicationGatewayOperatorSpecGenerator +} + func Test_ApplicationGatewayPathRule_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -5117,6 +5172,7 @@ func AddRelatedPropertyGeneratorsForApplicationGateway_Spec(gens map[string]gopt gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) gens["Listeners"] = gen.SliceOf(ApplicationGatewayListenerGenerator()) gens["LoadDistributionPolicies"] = gen.SliceOf(ApplicationGatewayLoadDistributionPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ApplicationGatewayOperatorSpecGenerator()) gens["PrivateLinkConfigurations"] = gen.SliceOf(ApplicationGatewayPrivateLinkConfigurationGenerator()) gens["Probes"] = gen.SliceOf(ApplicationGatewayProbeGenerator()) gens["RedirectConfigurations"] = gen.SliceOf(ApplicationGatewayRedirectConfigurationGenerator()) diff --git a/v2/api/network/v1api20220701/storage/bastion_host_types_gen.go b/v2/api/network/v1api20220701/storage/bastion_host_types_gen.go index 4b84544089a..5ff795c3fea 100644 --- a/v2/api/network/v1api20220701/storage/bastion_host_types_gen.go +++ b/v2/api/network/v1api20220701/storage/bastion_host_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (host *BastionHost) SetConditions(conditions conditions.Conditions) { host.Status.Conditions = conditions } +var _ configmaps.Exporter = &BastionHost{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (host *BastionHost) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if host.Spec.OperatorSpec == nil { + return nil + } + return host.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &BastionHost{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (host *BastionHost) SecretDestinationExpressions() []*core.DestinationExpression { + if host.Spec.OperatorSpec == nil { + return nil + } + return host.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &BastionHost{} // AzureName returns the Azure name of the resource @@ -151,6 +174,7 @@ type BastionHost_Spec struct { EnableTunneling *bool `json:"enableTunneling,omitempty"` IpConfigurations []BastionHostIPConfiguration `json:"ipConfigurations,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *BastionHostOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -244,6 +268,14 @@ type BastionHostIPConfiguration_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20220701.BastionHostOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BastionHostOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.Sku // The sku of this Bastion Host. type Sku struct { diff --git a/v2/api/network/v1api20220701/storage/bastion_host_types_gen_test.go b/v2/api/network/v1api20220701/storage/bastion_host_types_gen_test.go index 1c34d43e48f..73927fee4cd 100644 --- a/v2/api/network/v1api20220701/storage/bastion_host_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/bastion_host_types_gen_test.go @@ -216,6 +216,61 @@ func AddIndependentPropertyGeneratorsForBastionHostIPConfiguration_STATUS(gens m gens["Id"] = gen.PtrOf(gen.AlphaString()) } +func Test_BastionHostOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of BastionHostOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForBastionHostOperatorSpec, BastionHostOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForBastionHostOperatorSpec runs a test to see if a specific instance of BastionHostOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForBastionHostOperatorSpec(subject BastionHostOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual BastionHostOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of BastionHostOperatorSpec instances for property testing - lazily instantiated by +// BastionHostOperatorSpecGenerator() +var bastionHostOperatorSpecGenerator gopter.Gen + +// BastionHostOperatorSpecGenerator returns a generator of BastionHostOperatorSpec instances for property testing. +func BastionHostOperatorSpecGenerator() gopter.Gen { + if bastionHostOperatorSpecGenerator != nil { + return bastionHostOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + bastionHostOperatorSpecGenerator = gen.Struct(reflect.TypeOf(BastionHostOperatorSpec{}), generators) + + return bastionHostOperatorSpecGenerator +} + func Test_BastionHostSubResource_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -445,6 +500,7 @@ func AddIndependentPropertyGeneratorsForBastionHost_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForBastionHost_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForBastionHost_Spec(gens map[string]gopter.Gen) { gens["IpConfigurations"] = gen.SliceOf(BastionHostIPConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(BastionHostOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen.go b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen.go index 2a7144774af..fd9a0b8c837 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *DnsForwardingRuleSetsForwardingRule) SetConditions(conditions condit rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsForwardingRuleSetsForwardingRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *DnsForwardingRuleSetsForwardingRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleSetsForwardingRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *DnsForwardingRuleSetsForwardingRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsForwardingRuleSetsForwardingRule{} // AzureName returns the Azure name of the resource @@ -142,11 +165,12 @@ type DnsForwardingRuleSetsForwardingRuleList struct { type DnsForwardingRuleSetsForwardingRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DomainName *string `json:"domainName,omitempty"` - ForwardingRuleState *string `json:"forwardingRuleState,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DomainName *string `json:"domainName,omitempty"` + ForwardingRuleState *string `json:"forwardingRuleState,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *DnsForwardingRuleSetsForwardingRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -213,6 +237,14 @@ func (rule *DnsForwardingRuleSetsForwardingRule_STATUS) ConvertStatusTo(destinat return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20220701.DnsForwardingRuleSetsForwardingRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRuleSetsForwardingRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go index 91f690fa647..099b4f367f1 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_forwarding_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule(gens map gens["Status"] = DnsForwardingRuleSetsForwardingRule_STATUSGenerator() } +func Test_DnsForwardingRuleSetsForwardingRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRuleSetsForwardingRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec, DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec runs a test to see if a specific instance of DnsForwardingRuleSetsForwardingRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRuleSetsForwardingRuleOperatorSpec(subject DnsForwardingRuleSetsForwardingRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRuleSetsForwardingRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRuleSetsForwardingRuleOperatorSpec instances for property testing - lazily instantiated by +// DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator() +var dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator gopter.Gen + +// DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator returns a generator of DnsForwardingRuleSetsForwardingRuleOperatorSpec instances for property testing. +func DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator != nil { + return dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRuleSetsForwardingRuleOperatorSpec{}), generators) + + return dnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator +} + func Test_DnsForwardingRuleSetsForwardingRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -242,6 +297,7 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec // AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsForwardingRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRuleSetsForwardingRuleOperatorSpecGenerator()) gens["TargetDnsServers"] = gen.SliceOf(TargetDnsServerGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen.go b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen.go index 34d3a64d567..837aa4b56a0 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink) SetConditions(conditions co link.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsForwardingRuleSetsVirtualNetworkLink{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (link *DnsForwardingRuleSetsVirtualNetworkLink) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleSetsVirtualNetworkLink{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (link *DnsForwardingRuleSetsVirtualNetworkLink) SecretDestinationExpressions() []*core.DestinationExpression { + if link.Spec.OperatorSpec == nil { + return nil + } + return link.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsForwardingRuleSetsVirtualNetworkLink{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type DnsForwardingRuleSetsVirtualNetworkLinkList struct { type DnsForwardingRuleSetsVirtualNetworkLink_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -209,6 +233,14 @@ func (link *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) ConvertStatusTo(dest return destination.ConvertStatusFrom(link) } +// Storage version of v1api20220701.DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.DnsresolverSubResource // Reference to another ARM resource. type DnsresolverSubResource struct { diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go index 9e306c7dba9..51e70aad0bf 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_rule_sets_virtual_network_link_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink(gens gens["Status"] = DnsForwardingRuleSetsVirtualNetworkLink_STATUSGenerator() } +func Test_DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec, DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec runs a test to see if a specific instance of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec(subject DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec instances for property testing - lazily instantiated +// by DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator() +var dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator gopter.Gen + +// DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator returns a generator of DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec instances for property testing. +func DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator != nil { + return dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec{}), generators) + + return dnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator +} + func Test_DnsForwardingRuleSetsVirtualNetworkLink_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -238,6 +293,7 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_ // AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleSetsVirtualNetworkLink_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen.go b/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen.go index 5bffaa6382a..103ab25f5ff 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (ruleset *DnsForwardingRuleset) SetConditions(conditions conditions.Conditi ruleset.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsForwardingRuleset{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (ruleset *DnsForwardingRuleset) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if ruleset.Spec.OperatorSpec == nil { + return nil + } + return ruleset.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsForwardingRuleset{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (ruleset *DnsForwardingRuleset) SecretDestinationExpressions() []*core.DestinationExpression { + if ruleset.Spec.OperatorSpec == nil { + return nil + } + return ruleset.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsForwardingRuleset{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type DnsForwardingRulesetList struct { type DnsForwardingRuleset_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DnsResolverOutboundEndpoints []DnsresolverSubResource `json:"dnsResolverOutboundEndpoints,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DnsResolverOutboundEndpoints []DnsresolverSubResource `json:"dnsResolverOutboundEndpoints,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DnsForwardingRulesetOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -213,6 +237,14 @@ func (ruleset *DnsForwardingRuleset_STATUS) ConvertStatusTo(destination genrunti return destination.ConvertStatusFrom(ruleset) } +// Storage version of v1api20220701.DnsForwardingRulesetOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsForwardingRulesetOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsForwardingRuleset{}, &DnsForwardingRulesetList{}) } diff --git a/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen_test.go index 8e38317f540..a24e10ab522 100644 --- a/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_forwarding_ruleset_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsForwardingRuleset(gens map[string]gopter. gens["Status"] = DnsForwardingRuleset_STATUSGenerator() } +func Test_DnsForwardingRulesetOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsForwardingRulesetOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec, DnsForwardingRulesetOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec runs a test to see if a specific instance of DnsForwardingRulesetOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsForwardingRulesetOperatorSpec(subject DnsForwardingRulesetOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsForwardingRulesetOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsForwardingRulesetOperatorSpec instances for property testing - lazily instantiated by +// DnsForwardingRulesetOperatorSpecGenerator() +var dnsForwardingRulesetOperatorSpecGenerator gopter.Gen + +// DnsForwardingRulesetOperatorSpecGenerator returns a generator of DnsForwardingRulesetOperatorSpec instances for property testing. +func DnsForwardingRulesetOperatorSpecGenerator() gopter.Gen { + if dnsForwardingRulesetOperatorSpecGenerator != nil { + return dnsForwardingRulesetOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsForwardingRulesetOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsForwardingRulesetOperatorSpec{}), generators) + + return dnsForwardingRulesetOperatorSpecGenerator +} + func Test_DnsForwardingRuleset_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -242,4 +297,5 @@ func AddIndependentPropertyGeneratorsForDnsForwardingRuleset_Spec(gens map[strin // AddRelatedPropertyGeneratorsForDnsForwardingRuleset_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsForwardingRuleset_Spec(gens map[string]gopter.Gen) { gens["DnsResolverOutboundEndpoints"] = gen.SliceOf(DnsresolverSubResourceGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsForwardingRulesetOperatorSpecGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/dns_resolver_types_gen.go b/v2/api/network/v1api20220701/storage/dns_resolver_types_gen.go index 20f8cb8f52e..0e758a77524 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolver_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_resolver_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (resolver *DnsResolver) SetConditions(conditions conditions.Conditions) { resolver.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsResolver{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resolver *DnsResolver) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resolver.Spec.OperatorSpec == nil { + return nil + } + return resolver.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolver{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resolver *DnsResolver) SecretDestinationExpressions() []*core.DestinationExpression { + if resolver.Spec.OperatorSpec == nil { + return nil + } + return resolver.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsResolver{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type DnsResolverList struct { type DnsResolver_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DnsResolverOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -214,6 +238,14 @@ func (resolver *DnsResolver_STATUS) ConvertStatusTo(destination genruntime.Conve return destination.ConvertStatusFrom(resolver) } +// Storage version of v1api20220701.DnsResolverOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolverOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsResolver{}, &DnsResolverList{}) } diff --git a/v2/api/network/v1api20220701/storage/dns_resolver_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_resolver_types_gen_test.go index a96533c3ac9..08bd112de46 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolver_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_resolver_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForDnsResolver(gens map[string]gopter.Gen) { gens["Status"] = DnsResolver_STATUSGenerator() } +func Test_DnsResolverOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolverOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolverOperatorSpec, DnsResolverOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolverOperatorSpec runs a test to see if a specific instance of DnsResolverOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolverOperatorSpec(subject DnsResolverOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolverOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolverOperatorSpec instances for property testing - lazily instantiated by +// DnsResolverOperatorSpecGenerator() +var dnsResolverOperatorSpecGenerator gopter.Gen + +// DnsResolverOperatorSpecGenerator returns a generator of DnsResolverOperatorSpec instances for property testing. +func DnsResolverOperatorSpecGenerator() gopter.Gen { + if dnsResolverOperatorSpecGenerator != nil { + return dnsResolverOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolverOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolverOperatorSpec{}), generators) + + return dnsResolverOperatorSpecGenerator +} + func Test_DnsResolver_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -239,5 +294,6 @@ func AddIndependentPropertyGeneratorsForDnsResolver_Spec(gens map[string]gopter. // AddRelatedPropertyGeneratorsForDnsResolver_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolver_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsResolverOperatorSpecGenerator()) gens["VirtualNetwork"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen.go b/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen.go index c31e2d7a7cb..28722279f58 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *DnsResolversInboundEndpoint) SetConditions(conditions conditions endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsResolversInboundEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *DnsResolversInboundEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolversInboundEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *DnsResolversInboundEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsResolversInboundEndpoint{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type DnsResolversInboundEndpointList struct { type DnsResolversInboundEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - IpConfigurations []IpConfiguration `json:"ipConfigurations,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + IpConfigurations []IpConfiguration `json:"ipConfigurations,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DnsResolversInboundEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -212,6 +236,14 @@ func (endpoint *DnsResolversInboundEndpoint_STATUS) ConvertStatusTo(destination return destination.ConvertStatusFrom(endpoint) } +// Storage version of v1api20220701.DnsResolversInboundEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolversInboundEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.IpConfiguration // IP configuration. type IpConfiguration struct { diff --git a/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen_test.go index b3811e5ef5a..cb649fdb177 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_resolvers_inbound_endpoint_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint(gens map[string] gens["Status"] = DnsResolversInboundEndpoint_STATUSGenerator() } +func Test_DnsResolversInboundEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolversInboundEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec, DnsResolversInboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec runs a test to see if a specific instance of DnsResolversInboundEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolversInboundEndpointOperatorSpec(subject DnsResolversInboundEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolversInboundEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolversInboundEndpointOperatorSpec instances for property testing - lazily instantiated by +// DnsResolversInboundEndpointOperatorSpecGenerator() +var dnsResolversInboundEndpointOperatorSpecGenerator gopter.Gen + +// DnsResolversInboundEndpointOperatorSpecGenerator returns a generator of DnsResolversInboundEndpointOperatorSpec instances for property testing. +func DnsResolversInboundEndpointOperatorSpecGenerator() gopter.Gen { + if dnsResolversInboundEndpointOperatorSpecGenerator != nil { + return dnsResolversInboundEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolversInboundEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolversInboundEndpointOperatorSpec{}), generators) + + return dnsResolversInboundEndpointOperatorSpecGenerator +} + func Test_DnsResolversInboundEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -242,6 +297,7 @@ func AddIndependentPropertyGeneratorsForDnsResolversInboundEndpoint_Spec(gens ma // AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolversInboundEndpoint_Spec(gens map[string]gopter.Gen) { gens["IpConfigurations"] = gen.SliceOf(IpConfigurationGenerator()) + gens["OperatorSpec"] = gen.PtrOf(DnsResolversInboundEndpointOperatorSpecGenerator()) } func Test_IpConfiguration_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen.go b/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen.go index 472066be269..a434fd636fb 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *DnsResolversOutboundEndpoint) SetConditions(conditions condition endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &DnsResolversOutboundEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *DnsResolversOutboundEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &DnsResolversOutboundEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *DnsResolversOutboundEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &DnsResolversOutboundEndpoint{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type DnsResolversOutboundEndpointList struct { type DnsResolversOutboundEndpoint_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *DnsResolversOutboundEndpointOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -212,6 +236,14 @@ func (endpoint *DnsResolversOutboundEndpoint_STATUS) ConvertStatusTo(destination return destination.ConvertStatusFrom(endpoint) } +// Storage version of v1api20220701.DnsResolversOutboundEndpointOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DnsResolversOutboundEndpointOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&DnsResolversOutboundEndpoint{}, &DnsResolversOutboundEndpointList{}) } diff --git a/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen_test.go b/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen_test.go index b8690a94a88..29830017941 100644 --- a/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/dns_resolvers_outbound_endpoint_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint(gens map[string gens["Status"] = DnsResolversOutboundEndpoint_STATUSGenerator() } +func Test_DnsResolversOutboundEndpointOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of DnsResolversOutboundEndpointOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec, DnsResolversOutboundEndpointOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec runs a test to see if a specific instance of DnsResolversOutboundEndpointOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForDnsResolversOutboundEndpointOperatorSpec(subject DnsResolversOutboundEndpointOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual DnsResolversOutboundEndpointOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of DnsResolversOutboundEndpointOperatorSpec instances for property testing - lazily instantiated by +// DnsResolversOutboundEndpointOperatorSpecGenerator() +var dnsResolversOutboundEndpointOperatorSpecGenerator gopter.Gen + +// DnsResolversOutboundEndpointOperatorSpecGenerator returns a generator of DnsResolversOutboundEndpointOperatorSpec instances for property testing. +func DnsResolversOutboundEndpointOperatorSpecGenerator() gopter.Gen { + if dnsResolversOutboundEndpointOperatorSpecGenerator != nil { + return dnsResolversOutboundEndpointOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + dnsResolversOutboundEndpointOperatorSpecGenerator = gen.Struct(reflect.TypeOf(DnsResolversOutboundEndpointOperatorSpec{}), generators) + + return dnsResolversOutboundEndpointOperatorSpecGenerator +} + func Test_DnsResolversOutboundEndpoint_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -241,5 +296,6 @@ func AddIndependentPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec(gens m // AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForDnsResolversOutboundEndpoint_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(DnsResolversOutboundEndpointOperatorSpecGenerator()) gens["Subnet"] = gen.PtrOf(DnsresolverSubResourceGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/nat_gateway_types_gen.go b/v2/api/network/v1api20220701/storage/nat_gateway_types_gen.go index e8d7abd990c..05ab18e5bff 100644 --- a/v2/api/network/v1api20220701/storage/nat_gateway_types_gen.go +++ b/v2/api/network/v1api20220701/storage/nat_gateway_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (gateway *NatGateway) SetConditions(conditions conditions.Conditions) { gateway.Status.Conditions = conditions } +var _ configmaps.Exporter = &NatGateway{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (gateway *NatGateway) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NatGateway{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (gateway *NatGateway) SecretDestinationExpressions() []*core.DestinationExpression { + if gateway.Spec.OperatorSpec == nil { + return nil + } + return gateway.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NatGateway{} // AzureName returns the Azure name of the resource @@ -142,10 +165,11 @@ type NatGatewayList struct { type NatGateway_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - IdleTimeoutInMinutes *int `json:"idleTimeoutInMinutes,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + IdleTimeoutInMinutes *int `json:"idleTimeoutInMinutes,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *NatGatewayOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -221,6 +245,14 @@ func (gateway *NatGateway_STATUS) ConvertStatusTo(destination genruntime.Convert return destination.ConvertStatusFrom(gateway) } +// Storage version of v1api20220701.NatGatewayOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NatGatewayOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.NatGatewaySku // SKU of nat gateway. type NatGatewaySku struct { diff --git a/v2/api/network/v1api20220701/storage/nat_gateway_types_gen_test.go b/v2/api/network/v1api20220701/storage/nat_gateway_types_gen_test.go index efe910c8ed8..6387a8bdd2c 100644 --- a/v2/api/network/v1api20220701/storage/nat_gateway_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/nat_gateway_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForNatGateway(gens map[string]gopter.Gen) { gens["Status"] = NatGateway_STATUSGenerator() } +func Test_NatGatewayOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NatGatewayOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNatGatewayOperatorSpec, NatGatewayOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNatGatewayOperatorSpec runs a test to see if a specific instance of NatGatewayOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNatGatewayOperatorSpec(subject NatGatewayOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NatGatewayOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NatGatewayOperatorSpec instances for property testing - lazily instantiated by +// NatGatewayOperatorSpecGenerator() +var natGatewayOperatorSpecGenerator gopter.Gen + +// NatGatewayOperatorSpecGenerator returns a generator of NatGatewayOperatorSpec instances for property testing. +func NatGatewayOperatorSpecGenerator() gopter.Gen { + if natGatewayOperatorSpecGenerator != nil { + return natGatewayOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + natGatewayOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NatGatewayOperatorSpec{}), generators) + + return natGatewayOperatorSpecGenerator +} + func Test_NatGatewaySku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -365,6 +420,7 @@ func AddIndependentPropertyGeneratorsForNatGateway_Spec(gens map[string]gopter.G // AddRelatedPropertyGeneratorsForNatGateway_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNatGateway_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NatGatewayOperatorSpecGenerator()) gens["PublicIpAddresses"] = gen.SliceOf(ApplicationGatewaySubResourceGenerator()) gens["PublicIpPrefixes"] = gen.SliceOf(ApplicationGatewaySubResourceGenerator()) gens["Sku"] = gen.PtrOf(NatGatewaySkuGenerator()) diff --git a/v2/api/network/v1api20220701/storage/private_endpoint_types_gen.go b/v2/api/network/v1api20220701/storage/private_endpoint_types_gen.go index b96223989d3..a0c79abcb38 100644 --- a/v2/api/network/v1api20220701/storage/private_endpoint_types_gen.go +++ b/v2/api/network/v1api20220701/storage/private_endpoint_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (endpoint *PrivateEndpoint) SetConditions(conditions conditions.Conditions) endpoint.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateEndpoint{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (endpoint *PrivateEndpoint) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateEndpoint{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (endpoint *PrivateEndpoint) SecretDestinationExpressions() []*core.DestinationExpression { + if endpoint.Spec.OperatorSpec == nil { + return nil + } + return endpoint.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateEndpoint{} // AzureName returns the Azure name of the resource @@ -299,8 +322,10 @@ type PrivateEndpointIPConfiguration_STATUS struct { // Storage version of v1api20220701.PrivateEndpointOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PrivateEndpointOperatorSpec struct { - ConfigMaps *PrivateEndpointOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *PrivateEndpointOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20220701.PrivateLinkServiceConnection diff --git a/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen.go b/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen.go index 6a696253c5f..44a72807262 100644 --- a/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen.go +++ b/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *PrivateEndpointsPrivateDnsZoneGroup) SetConditions(conditions condi group.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateEndpointsPrivateDnsZoneGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *PrivateEndpointsPrivateDnsZoneGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateEndpointsPrivateDnsZoneGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *PrivateEndpointsPrivateDnsZoneGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PrivateEndpointsPrivateDnsZoneGroup{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type PrivateEndpointsPrivateDnsZoneGroupList struct { type PrivateEndpointsPrivateDnsZoneGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -224,6 +248,14 @@ type PrivateDnsZoneConfig_STATUS struct { RecordSets []RecordSet_STATUS `json:"recordSets,omitempty"` } +// Storage version of v1api20220701.PrivateEndpointsPrivateDnsZoneGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PrivateEndpointsPrivateDnsZoneGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.RecordSet_STATUS // A collective group of information about the record set information. type RecordSet_STATUS struct { diff --git a/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen_test.go b/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen_test.go index f00a45bd25d..417a90a84f3 100644 --- a/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/private_endpoints_private_dns_zone_group_types_gen_test.go @@ -216,6 +216,61 @@ func AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup(gens map gens["Status"] = PrivateEndpointsPrivateDnsZoneGroup_STATUSGenerator() } +func Test_PrivateEndpointsPrivateDnsZoneGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec, PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec runs a test to see if a specific instance of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPrivateEndpointsPrivateDnsZoneGroupOperatorSpec(subject PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PrivateEndpointsPrivateDnsZoneGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec instances for property testing - lazily instantiated by +// PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator() +var privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator gopter.Gen + +// PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator returns a generator of PrivateEndpointsPrivateDnsZoneGroupOperatorSpec instances for property testing. +func PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator() gopter.Gen { + if privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator != nil { + return privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec{}), generators) + + return privateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator +} + func Test_PrivateEndpointsPrivateDnsZoneGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -367,6 +422,7 @@ func AddIndependentPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec // AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForPrivateEndpointsPrivateDnsZoneGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(PrivateEndpointsPrivateDnsZoneGroupOperatorSpecGenerator()) gens["PrivateDnsZoneConfigs"] = gen.SliceOf(PrivateDnsZoneConfigGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/private_link_service_types_gen.go b/v2/api/network/v1api20220701/storage/private_link_service_types_gen.go index 67071e302f9..a4b8dab9e56 100644 --- a/v2/api/network/v1api20220701/storage/private_link_service_types_gen.go +++ b/v2/api/network/v1api20220701/storage/private_link_service_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (service *PrivateLinkService) SetConditions(conditions conditions.Condition service.Status.Conditions = conditions } +var _ configmaps.Exporter = &PrivateLinkService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *PrivateLinkService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PrivateLinkService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *PrivateLinkService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &PrivateLinkService{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -311,8 +333,10 @@ type PrivateLinkServiceIpConfiguration_STATUS struct { // Storage version of v1api20220701.PrivateLinkServiceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PrivateLinkServiceOperatorSpec struct { - ConfigMaps *PrivateLinkServiceOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *PrivateLinkServiceOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20220701.ResourceSet diff --git a/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen.go b/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen.go index c07a444c5a8..9d76c485880 100644 --- a/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen.go +++ b/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (prefix *PublicIPPrefix) SetConditions(conditions conditions.Conditions) { prefix.Status.Conditions = conditions } +var _ configmaps.Exporter = &PublicIPPrefix{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (prefix *PublicIPPrefix) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if prefix.Spec.OperatorSpec == nil { + return nil + } + return prefix.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &PublicIPPrefix{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (prefix *PublicIPPrefix) SecretDestinationExpressions() []*core.DestinationExpression { + if prefix.Spec.OperatorSpec == nil { + return nil + } + return prefix.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &PublicIPPrefix{} // AzureName returns the Azure name of the resource @@ -148,6 +171,7 @@ type PublicIPPrefix_Spec struct { IpTags []IpTag `json:"ipTags,omitempty"` Location *string `json:"location,omitempty"` NatGateway *NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded `json:"natGateway,omitempty"` + OperatorSpec *PublicIPPrefixOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -261,6 +285,14 @@ type NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded struct { Reference *genruntime.ResourceReference `armReference:"Id" json:"reference,omitempty"` } +// Storage version of v1api20220701.PublicIPPrefixOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type PublicIPPrefixOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220701.PublicIPPrefixSku // SKU of a public IP prefix. type PublicIPPrefixSku struct { diff --git a/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen_test.go b/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen_test.go index dd157dc24fc..68ff75efc88 100644 --- a/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen_test.go +++ b/v2/api/network/v1api20220701/storage/public_ip_prefix_types_gen_test.go @@ -316,6 +316,61 @@ func AddRelatedPropertyGeneratorsForPublicIPPrefix(gens map[string]gopter.Gen) { gens["Status"] = PublicIPPrefix_STATUSGenerator() } +func Test_PublicIPPrefixOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of PublicIPPrefixOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForPublicIPPrefixOperatorSpec, PublicIPPrefixOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForPublicIPPrefixOperatorSpec runs a test to see if a specific instance of PublicIPPrefixOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForPublicIPPrefixOperatorSpec(subject PublicIPPrefixOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual PublicIPPrefixOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of PublicIPPrefixOperatorSpec instances for property testing - lazily instantiated by +// PublicIPPrefixOperatorSpecGenerator() +var publicIPPrefixOperatorSpecGenerator gopter.Gen + +// PublicIPPrefixOperatorSpecGenerator returns a generator of PublicIPPrefixOperatorSpec instances for property testing. +func PublicIPPrefixOperatorSpecGenerator() gopter.Gen { + if publicIPPrefixOperatorSpecGenerator != nil { + return publicIPPrefixOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + publicIPPrefixOperatorSpecGenerator = gen.Struct(reflect.TypeOf(PublicIPPrefixOperatorSpec{}), generators) + + return publicIPPrefixOperatorSpecGenerator +} + func Test_PublicIPPrefixSku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -617,6 +672,7 @@ func AddRelatedPropertyGeneratorsForPublicIPPrefix_Spec(gens map[string]gopter.G gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["IpTags"] = gen.SliceOf(IpTagGenerator()) gens["NatGateway"] = gen.PtrOf(NatGatewaySpec_PublicIPPrefix_SubResourceEmbeddedGenerator()) + gens["OperatorSpec"] = gen.PtrOf(PublicIPPrefixOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(PublicIPPrefixSkuGenerator()) } diff --git a/v2/api/network/v1api20220701/storage/structure.txt b/v2/api/network/v1api20220701/storage/structure.txt index b1abb35d0bf..9c6d83b2b56 100644 --- a/v2/api/network/v1api20220701/storage/structure.txt +++ b/v2/api/network/v1api20220701/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-07-01" ApplicationGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (39 properties) +├── Spec: Object (40 properties) │ ├── AuthenticationCertificates: Object (3 properties)[] │ │ ├── Data: *genruntime.SecretReference │ │ ├── Name: *string @@ -155,6 +155,10 @@ ApplicationGateway: Resource │ │ ├── Name: *string │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkConfigurations: Object (3 properties)[] @@ -493,7 +497,7 @@ ApplicationGateway: Resource └── Zones: string[] BastionHost: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AzureName: string │ ├── DisableCopyPaste: *bool │ ├── DnsName: *string @@ -512,6 +516,10 @@ BastionHost: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -545,11 +553,15 @@ BastionHost: Resource └── Type: *string DnsForwardingRuleSetsForwardingRule: Resource ├── Owner: network/v1api20220701.DnsForwardingRuleset -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AzureName: string │ ├── DomainName: *string │ ├── ForwardingRuleState: *string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -583,9 +595,13 @@ DnsForwardingRuleSetsForwardingRule: Resource └── Type: *string DnsForwardingRuleSetsVirtualNetworkLink: Resource ├── Owner: network/v1api20220701.DnsForwardingRuleset -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -614,12 +630,16 @@ DnsForwardingRuleSetsVirtualNetworkLink: Resource └── PropertyBag: genruntime.PropertyBag DnsForwardingRuleset: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── DnsResolverOutboundEndpoints: Object (2 properties)[] │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -648,9 +668,13 @@ DnsForwardingRuleset: Resource └── Type: *string DnsResolver: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -683,7 +707,7 @@ DnsResolver: Resource └── PropertyBag: genruntime.PropertyBag DnsResolversInboundEndpoint: Resource ├── Owner: network/v1api20220701.DnsResolver -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── IpConfigurations: Object (4 properties)[] │ │ ├── PrivateIpAddress: *string @@ -693,6 +717,10 @@ DnsResolversInboundEndpoint: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -725,9 +753,13 @@ DnsResolversInboundEndpoint: Resource └── Type: *string DnsResolversOutboundEndpoint: Resource ├── Owner: network/v1api20220701.DnsResolver -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -759,10 +791,14 @@ DnsResolversOutboundEndpoint: Resource └── Type: *string NatGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── IdleTimeoutInMinutes: *int │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -832,11 +868,13 @@ PrivateEndpoint: Resource │ │ ├── PrivateLinkServiceReference: *genruntime.ResourceReference │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── RequestMessage: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── PrimaryNicPrivateIpAddress: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkServiceConnections: Object (6 properties)[] @@ -923,8 +961,12 @@ PrivateEndpoint: Resource └── Type: *string PrivateEndpointsPrivateDnsZoneGroup: Resource ├── Owner: network/v1api20220701.PrivateEndpoint -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateDnsZoneConfigs: Object (3 properties)[] @@ -978,11 +1020,13 @@ PrivateLinkService: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── Alias: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1038,7 +1082,7 @@ PrivateLinkService: Resource └── Subscriptions: string[] PublicIPPrefix: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AzureName: string │ ├── CustomIPPrefix: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag @@ -1055,6 +1099,10 @@ PublicIPPrefix: Resource │ ├── NatGateway: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrefixLength: *int diff --git a/v2/api/network/v1api20220701/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20220701/storage/zz_generated.deepcopy.go index b8529d90a59..d0e1d222623 100644 --- a/v2/api/network/v1api20220701/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20220701/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1341,6 +1342,50 @@ func (in *ApplicationGatewayLoadDistributionTarget) DeepCopy() *ApplicationGatew return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationGatewayOperatorSpec) DeepCopyInto(out *ApplicationGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationGatewayOperatorSpec. +func (in *ApplicationGatewayOperatorSpec) DeepCopy() *ApplicationGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(ApplicationGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationGatewayPathRule) DeepCopyInto(out *ApplicationGatewayPathRule) { *out = *in @@ -3262,6 +3307,11 @@ func (in *ApplicationGateway_Spec) DeepCopyInto(out *ApplicationGateway_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApplicationGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3572,6 +3622,50 @@ func (in *BastionHostList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BastionHostOperatorSpec) DeepCopyInto(out *BastionHostOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionHostOperatorSpec. +func (in *BastionHostOperatorSpec) DeepCopy() *BastionHostOperatorSpec { + if in == nil { + return nil + } + out := new(BastionHostOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionHostSubResource) DeepCopyInto(out *BastionHostSubResource) { *out = *in @@ -3757,6 +3851,11 @@ func (in *BastionHost_Spec) DeepCopyInto(out *BastionHost_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BastionHostOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3889,6 +3988,50 @@ func (in *DnsForwardingRuleSetsForwardingRuleList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRuleSetsForwardingRuleOperatorSpec) DeepCopyInto(out *DnsForwardingRuleSetsForwardingRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRuleSetsForwardingRuleOperatorSpec. +func (in *DnsForwardingRuleSetsForwardingRuleOperatorSpec) DeepCopy() *DnsForwardingRuleSetsForwardingRuleOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRuleSetsForwardingRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleSetsForwardingRule_STATUS) DeepCopyInto(out *DnsForwardingRuleSetsForwardingRule_STATUS) { *out = *in @@ -3992,6 +4135,11 @@ func (in *DnsForwardingRuleSetsForwardingRule_Spec) DeepCopyInto(out *DnsForward (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRuleSetsForwardingRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4082,6 +4230,50 @@ func (in *DnsForwardingRuleSetsVirtualNetworkLinkList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) DeepCopyInto(out *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec. +func (in *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) DeepCopy() *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) DeepCopyInto(out *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) { *out = *in @@ -4163,6 +4355,11 @@ func (in *DnsForwardingRuleSetsVirtualNetworkLink_Spec) DeepCopyInto(out *DnsFor (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4251,6 +4448,50 @@ func (in *DnsForwardingRulesetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRulesetOperatorSpec) DeepCopyInto(out *DnsForwardingRulesetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRulesetOperatorSpec. +func (in *DnsForwardingRulesetOperatorSpec) DeepCopy() *DnsForwardingRulesetOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRulesetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleset_STATUS) DeepCopyInto(out *DnsForwardingRuleset_STATUS) { *out = *in @@ -4349,6 +4590,11 @@ func (in *DnsForwardingRuleset_Spec) DeepCopyInto(out *DnsForwardingRuleset_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRulesetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4439,6 +4685,50 @@ func (in *DnsResolverList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolverOperatorSpec) DeepCopyInto(out *DnsResolverOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolverOperatorSpec. +func (in *DnsResolverOperatorSpec) DeepCopy() *DnsResolverOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolverOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolver_STATUS) DeepCopyInto(out *DnsResolver_STATUS) { *out = *in @@ -4533,6 +4823,11 @@ func (in *DnsResolver_Spec) DeepCopyInto(out *DnsResolver_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolverOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4628,6 +4923,50 @@ func (in *DnsResolversInboundEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolversInboundEndpointOperatorSpec) DeepCopyInto(out *DnsResolversInboundEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolversInboundEndpointOperatorSpec. +func (in *DnsResolversInboundEndpointOperatorSpec) DeepCopy() *DnsResolversInboundEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolversInboundEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolversInboundEndpoint_STATUS) DeepCopyInto(out *DnsResolversInboundEndpoint_STATUS) { *out = *in @@ -4726,6 +5065,11 @@ func (in *DnsResolversInboundEndpoint_Spec) DeepCopyInto(out *DnsResolversInboun *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolversInboundEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4816,6 +5160,50 @@ func (in *DnsResolversOutboundEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolversOutboundEndpointOperatorSpec) DeepCopyInto(out *DnsResolversOutboundEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolversOutboundEndpointOperatorSpec. +func (in *DnsResolversOutboundEndpointOperatorSpec) DeepCopy() *DnsResolversOutboundEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolversOutboundEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolversOutboundEndpoint_STATUS) DeepCopyInto(out *DnsResolversOutboundEndpoint_STATUS) { *out = *in @@ -4905,6 +5293,11 @@ func (in *DnsResolversOutboundEndpoint_Spec) DeepCopyInto(out *DnsResolversOutbo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolversOutboundEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5420,6 +5813,50 @@ func (in *NatGatewayList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NatGatewayOperatorSpec) DeepCopyInto(out *NatGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NatGatewayOperatorSpec. +func (in *NatGatewayOperatorSpec) DeepCopy() *NatGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(NatGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NatGatewaySku) DeepCopyInto(out *NatGatewaySku) { *out = *in @@ -5648,6 +6085,11 @@ func (in *NatGateway_Spec) DeepCopyInto(out *NatGateway_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NatGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6038,6 +6480,17 @@ func (in *PrivateEndpointOperatorConfigMaps) DeepCopy() *PrivateEndpointOperator // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointOperatorSpec) DeepCopyInto(out *PrivateEndpointOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(PrivateEndpointOperatorConfigMaps) @@ -6050,6 +6503,17 @@ func (in *PrivateEndpointOperatorSpec) DeepCopyInto(out *PrivateEndpointOperator (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateEndpointOperatorSpec. @@ -6331,6 +6795,50 @@ func (in *PrivateEndpointsPrivateDnsZoneGroupList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateEndpointsPrivateDnsZoneGroupOperatorSpec. +func (in *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) DeepCopy() *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointsPrivateDnsZoneGroup_STATUS) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroup_STATUS) { *out = *in @@ -6390,6 +6898,11 @@ func (in *PrivateEndpointsPrivateDnsZoneGroup_STATUS) DeepCopy() *PrivateEndpoin // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointsPrivateDnsZoneGroup_Spec) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroup_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -6822,6 +7335,17 @@ func (in *PrivateLinkServiceOperatorConfigMaps) DeepCopy() *PrivateLinkServiceOp // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateLinkServiceOperatorSpec) DeepCopyInto(out *PrivateLinkServiceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(PrivateLinkServiceOperatorConfigMaps) @@ -6834,6 +7358,17 @@ func (in *PrivateLinkServiceOperatorSpec) DeepCopyInto(out *PrivateLinkServiceOp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateLinkServiceOperatorSpec. @@ -7112,6 +7647,50 @@ func (in *PublicIPPrefixList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PublicIPPrefixOperatorSpec) DeepCopyInto(out *PublicIPPrefixOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PublicIPPrefixOperatorSpec. +func (in *PublicIPPrefixOperatorSpec) DeepCopy() *PublicIPPrefixOperatorSpec { + if in == nil { + return nil + } + out := new(PublicIPPrefixOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PublicIPPrefixSku) DeepCopyInto(out *PublicIPPrefixSku) { *out = *in @@ -7336,6 +7915,11 @@ func (in *PublicIPPrefix_Spec) DeepCopyInto(out *PublicIPPrefix_Spec) { *out = new(NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PublicIPPrefixOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20220701/structure.txt b/v2/api/network/v1api20220701/structure.txt index 7b92c75e216..b1da0fcf861 100644 --- a/v2/api/network/v1api20220701/structure.txt +++ b/v2/api/network/v1api20220701/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-07-01" ApplicationGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (37 properties) +├── Spec: Object (38 properties) │ ├── AuthenticationCertificates: Object (2 properties)[] │ │ ├── Data: *genruntime.SecretReference │ │ └── Name: *string @@ -152,6 +152,9 @@ ApplicationGateway: Resource │ │ │ └── Reference: *genruntime.ResourceReference │ │ └── Name: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkConfigurations: Object (2 properties)[] │ │ ├── IpConfigurations: Object (1 property)[] @@ -604,7 +607,7 @@ ApplicationGateway: Resource └── Zones: string[] BastionHost: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: string │ ├── DisableCopyPaste: *bool │ ├── DnsName: *string @@ -622,6 +625,9 @@ BastionHost: Resource │ │ └── Subnet: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ScaleUnits: Validated<*int> (2 rules) │ │ ├── Rule 0: Maximum: 50 @@ -659,13 +665,16 @@ BastionHost: Resource └── Type: *string DnsForwardingRuleSetsForwardingRule: Resource ├── Owner: DnsForwardingRuleset -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── DomainName: *string │ ├── ForwardingRuleState: *Enum (2 values) │ │ ├── "Disabled" │ │ └── "Enabled" │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── TargetDnsServers: Object (3 properties)[] │ ├── IpAddress: *string @@ -709,9 +718,12 @@ DnsForwardingRuleSetsForwardingRule: Resource └── Type: *string DnsForwardingRuleSetsVirtualNetworkLink: Resource ├── Owner: DnsForwardingRuleset -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── VirtualNetwork: *Object (1 property) │ └── Reference: *genruntime.ResourceReference @@ -748,11 +760,14 @@ DnsForwardingRuleSetsVirtualNetworkLink: Resource └── Id: *string DnsForwardingRuleset: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── DnsResolverOutboundEndpoints: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (11 properties) @@ -790,9 +805,12 @@ DnsForwardingRuleset: Resource └── Type: *string DnsResolver: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Tags: map[string]string │ └── VirtualNetwork: *Object (1 property) @@ -835,7 +853,7 @@ DnsResolver: Resource └── Id: *string DnsResolversInboundEndpoint: Resource ├── Owner: DnsResolver -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── IpConfigurations: Object (3 properties)[] │ │ ├── PrivateIpAddress: *string @@ -845,6 +863,9 @@ DnsResolversInboundEndpoint: Resource │ │ └── Subnet: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (11 properties) @@ -887,9 +908,12 @@ DnsResolversInboundEndpoint: Resource └── Type: *string DnsResolversOutboundEndpoint: Resource ├── Owner: DnsResolver -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Subnet: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -929,10 +953,13 @@ DnsResolversOutboundEndpoint: Resource └── Type: *string NatGateway: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── IdleTimeoutInMinutes: *int │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicIpAddresses: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference @@ -994,9 +1021,11 @@ PrivateEndpoint: Resource │ │ │ └── Status: *string │ │ ├── PrivateLinkServiceReference: *genruntime.ResourceReference │ │ └── RequestMessage: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── PrimaryNicPrivateIpAddress: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── PrimaryNicPrivateIpAddress: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrivateLinkServiceConnections: Object (5 properties)[] │ │ ├── GroupIds: string[] @@ -1080,8 +1109,11 @@ PrivateEndpoint: Resource └── Type: *string PrivateEndpointsPrivateDnsZoneGroup: Resource ├── Owner: PrivateEndpoint -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── PrivateDnsZoneConfigs: Object (2 properties)[] │ ├── Name: *string @@ -1137,9 +1169,11 @@ PrivateLinkService: Resource │ ├── LoadBalancerFrontendIpConfigurations: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── Alias: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── Alias: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Tags: map[string]string │ └── Visibility: *Object (1 property) @@ -1196,7 +1230,7 @@ PrivateLinkService: Resource └── Subscriptions: string[] PublicIPPrefix: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AzureName: string │ ├── CustomIPPrefix: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference @@ -1210,6 +1244,9 @@ PublicIPPrefix: Resource │ ├── Location: *string │ ├── NatGateway: *Object (1 property) │ │ └── Reference: *genruntime.ResourceReference +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrefixLength: *int │ ├── PublicIPAddressVersion: *Enum (2 values) diff --git a/v2/api/network/v1api20220701/zz_generated.deepcopy.go b/v2/api/network/v1api20220701/zz_generated.deepcopy.go index 959e69e28ce..2f8bdf64d64 100644 --- a/v2/api/network/v1api20220701/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20220701/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220701 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1096,6 +1097,43 @@ func (in *ApplicationGatewayLoadDistributionTarget) DeepCopy() *ApplicationGatew return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationGatewayOperatorSpec) DeepCopyInto(out *ApplicationGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationGatewayOperatorSpec. +func (in *ApplicationGatewayOperatorSpec) DeepCopy() *ApplicationGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(ApplicationGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationGatewayPathRule) DeepCopyInto(out *ApplicationGatewayPathRule) { *out = *in @@ -2744,6 +2782,11 @@ func (in *ApplicationGateway_Spec) DeepCopyInto(out *ApplicationGateway_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApplicationGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3019,6 +3062,43 @@ func (in *BastionHostList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BastionHostOperatorSpec) DeepCopyInto(out *BastionHostOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionHostOperatorSpec. +func (in *BastionHostOperatorSpec) DeepCopy() *BastionHostOperatorSpec { + if in == nil { + return nil + } + out := new(BastionHostOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionHostSubResource) DeepCopyInto(out *BastionHostSubResource) { *out = *in @@ -3190,6 +3270,11 @@ func (in *BastionHost_Spec) DeepCopyInto(out *BastionHost_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(BastionHostOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3308,6 +3393,43 @@ func (in *DnsForwardingRuleSetsForwardingRuleList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRuleSetsForwardingRuleOperatorSpec) DeepCopyInto(out *DnsForwardingRuleSetsForwardingRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRuleSetsForwardingRuleOperatorSpec. +func (in *DnsForwardingRuleSetsForwardingRuleOperatorSpec) DeepCopy() *DnsForwardingRuleSetsForwardingRuleOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRuleSetsForwardingRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleSetsForwardingRule_STATUS) DeepCopyInto(out *DnsForwardingRuleSetsForwardingRule_STATUS) { *out = *in @@ -3404,6 +3526,11 @@ func (in *DnsForwardingRuleSetsForwardingRule_Spec) DeepCopyInto(out *DnsForward (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRuleSetsForwardingRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3487,6 +3614,43 @@ func (in *DnsForwardingRuleSetsVirtualNetworkLinkList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) DeepCopyInto(out *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec. +func (in *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) DeepCopy() *DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) DeepCopyInto(out *DnsForwardingRuleSetsVirtualNetworkLink_STATUS) { *out = *in @@ -3561,6 +3725,11 @@ func (in *DnsForwardingRuleSetsVirtualNetworkLink_Spec) DeepCopyInto(out *DnsFor (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRuleSetsVirtualNetworkLinkOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3642,6 +3811,43 @@ func (in *DnsForwardingRulesetList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsForwardingRulesetOperatorSpec) DeepCopyInto(out *DnsForwardingRulesetOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsForwardingRulesetOperatorSpec. +func (in *DnsForwardingRulesetOperatorSpec) DeepCopy() *DnsForwardingRulesetOperatorSpec { + if in == nil { + return nil + } + out := new(DnsForwardingRulesetOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsForwardingRuleset_STATUS) DeepCopyInto(out *DnsForwardingRuleset_STATUS) { *out = *in @@ -3733,6 +3939,11 @@ func (in *DnsForwardingRuleset_Spec) DeepCopyInto(out *DnsForwardingRuleset_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsForwardingRulesetOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3816,6 +4027,43 @@ func (in *DnsResolverList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolverOperatorSpec) DeepCopyInto(out *DnsResolverOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolverOperatorSpec. +func (in *DnsResolverOperatorSpec) DeepCopy() *DnsResolverOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolverOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolver_STATUS) DeepCopyInto(out *DnsResolver_STATUS) { *out = *in @@ -3903,6 +4151,11 @@ func (in *DnsResolver_Spec) DeepCopyInto(out *DnsResolver_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolverOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3991,6 +4244,43 @@ func (in *DnsResolversInboundEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolversInboundEndpointOperatorSpec) DeepCopyInto(out *DnsResolversInboundEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolversInboundEndpointOperatorSpec. +func (in *DnsResolversInboundEndpointOperatorSpec) DeepCopy() *DnsResolversInboundEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolversInboundEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolversInboundEndpoint_STATUS) DeepCopyInto(out *DnsResolversInboundEndpoint_STATUS) { *out = *in @@ -4082,6 +4372,11 @@ func (in *DnsResolversInboundEndpoint_Spec) DeepCopyInto(out *DnsResolversInboun *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolversInboundEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4165,6 +4460,43 @@ func (in *DnsResolversOutboundEndpointList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DnsResolversOutboundEndpointOperatorSpec) DeepCopyInto(out *DnsResolversOutboundEndpointOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DnsResolversOutboundEndpointOperatorSpec. +func (in *DnsResolversOutboundEndpointOperatorSpec) DeepCopy() *DnsResolversOutboundEndpointOperatorSpec { + if in == nil { + return nil + } + out := new(DnsResolversOutboundEndpointOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DnsResolversOutboundEndpoint_STATUS) DeepCopyInto(out *DnsResolversOutboundEndpoint_STATUS) { *out = *in @@ -4247,6 +4579,11 @@ func (in *DnsResolversOutboundEndpoint_Spec) DeepCopyInto(out *DnsResolversOutbo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(DnsResolversOutboundEndpointOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4662,6 +4999,43 @@ func (in *NatGatewayList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NatGatewayOperatorSpec) DeepCopyInto(out *NatGatewayOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NatGatewayOperatorSpec. +func (in *NatGatewayOperatorSpec) DeepCopy() *NatGatewayOperatorSpec { + if in == nil { + return nil + } + out := new(NatGatewayOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NatGatewaySku) DeepCopyInto(out *NatGatewaySku) { *out = *in @@ -4855,6 +5229,11 @@ func (in *NatGateway_Spec) DeepCopyInto(out *NatGateway_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NatGatewayOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5182,11 +5561,33 @@ func (in *PrivateEndpointOperatorConfigMaps) DeepCopy() *PrivateEndpointOperator // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointOperatorSpec) DeepCopyInto(out *PrivateEndpointOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(PrivateEndpointOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateEndpointOperatorSpec. @@ -5454,6 +5855,43 @@ func (in *PrivateEndpointsPrivateDnsZoneGroupList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateEndpointsPrivateDnsZoneGroupOperatorSpec. +func (in *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) DeepCopy() *PrivateEndpointsPrivateDnsZoneGroupOperatorSpec { + if in == nil { + return nil + } + out := new(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointsPrivateDnsZoneGroup_STATUS) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroup_STATUS) { *out = *in @@ -5506,6 +5944,11 @@ func (in *PrivateEndpointsPrivateDnsZoneGroup_STATUS) DeepCopy() *PrivateEndpoin // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateEndpointsPrivateDnsZoneGroup_Spec) DeepCopyInto(out *PrivateEndpointsPrivateDnsZoneGroup_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PrivateEndpointsPrivateDnsZoneGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5882,11 +6325,33 @@ func (in *PrivateLinkServiceOperatorConfigMaps) DeepCopy() *PrivateLinkServiceOp // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PrivateLinkServiceOperatorSpec) DeepCopyInto(out *PrivateLinkServiceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(PrivateLinkServiceOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateLinkServiceOperatorSpec. @@ -6151,6 +6616,43 @@ func (in *PublicIPPrefixList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PublicIPPrefixOperatorSpec) DeepCopyInto(out *PublicIPPrefixOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PublicIPPrefixOperatorSpec. +func (in *PublicIPPrefixOperatorSpec) DeepCopy() *PublicIPPrefixOperatorSpec { + if in == nil { + return nil + } + out := new(PublicIPPrefixOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PublicIPPrefixSku) DeepCopyInto(out *PublicIPPrefixSku) { *out = *in @@ -6354,6 +6856,11 @@ func (in *PublicIPPrefix_Spec) DeepCopyInto(out *PublicIPPrefix_Spec) { *out = new(NatGatewaySpec_PublicIPPrefix_SubResourceEmbedded) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(PublicIPPrefixOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20240101/application_security_group_types_gen.go b/v2/api/network/v1api20240101/application_security_group_types_gen.go index ed686a63577..0a3154386b7 100644 --- a/v2/api/network/v1api20240101/application_security_group_types_gen.go +++ b/v2/api/network/v1api20240101/application_security_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *ApplicationSecurityGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the ApplicationSecurityGroup resource func (group *ApplicationSecurityGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &ApplicationSecurityGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ApplicationSecurityGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApplicationSecurityGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ApplicationSecurityGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ApplicationSecurityGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *ApplicationSecurityGroup) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (group *ApplicationSecurityGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (group *ApplicationSecurityGroup) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *ApplicationSecurityGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (group *ApplicationSecurityGroup) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(group) @@ -244,6 +281,14 @@ func (group *ApplicationSecurityGroup) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *ApplicationSecurityGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *ApplicationSecurityGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ApplicationSecurityGroup) @@ -338,6 +383,10 @@ type ApplicationSecurityGroup_Spec struct { // Location: Resource location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ApplicationSecurityGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -397,6 +446,8 @@ func (group *ApplicationSecurityGroup_Spec) PopulateFromARM(owner genruntime.Arb group.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -474,6 +525,18 @@ func (group *ApplicationSecurityGroup_Spec) AssignProperties_From_ApplicationSec // Location group.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ApplicationSecurityGroupOperatorSpec + err := operatorSpec.AssignProperties_From_ApplicationSecurityGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ApplicationSecurityGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -500,6 +563,18 @@ func (group *ApplicationSecurityGroup_Spec) AssignProperties_To_ApplicationSecur // Location destination.Location = genruntime.ClonePointerToString(group.Location) + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.ApplicationSecurityGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_ApplicationSecurityGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ApplicationSecurityGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -795,6 +870,110 @@ func (group *ApplicationSecurityGroup_STATUS) AssignProperties_To_ApplicationSec return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApplicationSecurityGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ApplicationSecurityGroupOperatorSpec populates our ApplicationSecurityGroupOperatorSpec from the provided source ApplicationSecurityGroupOperatorSpec +func (operator *ApplicationSecurityGroupOperatorSpec) AssignProperties_From_ApplicationSecurityGroupOperatorSpec(source *storage.ApplicationSecurityGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ApplicationSecurityGroupOperatorSpec populates the provided destination ApplicationSecurityGroupOperatorSpec from our ApplicationSecurityGroupOperatorSpec +func (operator *ApplicationSecurityGroupOperatorSpec) AssignProperties_To_ApplicationSecurityGroupOperatorSpec(destination *storage.ApplicationSecurityGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The current provisioning state. type ProvisioningState_STATUS string diff --git a/v2/api/network/v1api20240101/application_security_group_types_gen_test.go b/v2/api/network/v1api20240101/application_security_group_types_gen_test.go index 4256813c9a1..fa54d9d004f 100644 --- a/v2/api/network/v1api20240101/application_security_group_types_gen_test.go +++ b/v2/api/network/v1api20240101/application_security_group_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForApplicationSecurityGroup(gens map[string]gop gens["Status"] = ApplicationSecurityGroup_STATUSGenerator() } +func Test_ApplicationSecurityGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ApplicationSecurityGroupOperatorSpec to ApplicationSecurityGroupOperatorSpec via AssignProperties_To_ApplicationSecurityGroupOperatorSpec & AssignProperties_From_ApplicationSecurityGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForApplicationSecurityGroupOperatorSpec, ApplicationSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForApplicationSecurityGroupOperatorSpec tests if a specific instance of ApplicationSecurityGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForApplicationSecurityGroupOperatorSpec(subject ApplicationSecurityGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ApplicationSecurityGroupOperatorSpec + err := copied.AssignProperties_To_ApplicationSecurityGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ApplicationSecurityGroupOperatorSpec + err = actual.AssignProperties_From_ApplicationSecurityGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ApplicationSecurityGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApplicationSecurityGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec, ApplicationSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec runs a test to see if a specific instance of ApplicationSecurityGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec(subject ApplicationSecurityGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApplicationSecurityGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApplicationSecurityGroupOperatorSpec instances for property testing - lazily instantiated by +// ApplicationSecurityGroupOperatorSpecGenerator() +var applicationSecurityGroupOperatorSpecGenerator gopter.Gen + +// ApplicationSecurityGroupOperatorSpecGenerator returns a generator of ApplicationSecurityGroupOperatorSpec instances for property testing. +func ApplicationSecurityGroupOperatorSpecGenerator() gopter.Gen { + if applicationSecurityGroupOperatorSpecGenerator != nil { + return applicationSecurityGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + applicationSecurityGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroupOperatorSpec{}), generators) + + return applicationSecurityGroupOperatorSpecGenerator +} + func Test_ApplicationSecurityGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -367,6 +464,9 @@ func RunJSONSerializationTestForApplicationSecurityGroup_Spec(subject Applicatio var applicationSecurityGroup_SpecGenerator gopter.Gen // ApplicationSecurityGroup_SpecGenerator returns a generator of ApplicationSecurityGroup_Spec instances for property testing. +// We first initialize applicationSecurityGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApplicationSecurityGroup_SpecGenerator() gopter.Gen { if applicationSecurityGroup_SpecGenerator != nil { return applicationSecurityGroup_SpecGenerator @@ -376,6 +476,12 @@ func ApplicationSecurityGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) applicationSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) + AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) + applicationSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroup_Spec{}), generators) + return applicationSecurityGroup_SpecGenerator } @@ -387,3 +493,8 @@ func AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(gens map[s gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApplicationSecurityGroupOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20240101/storage/application_security_group_types_gen.go b/v2/api/network/v1api20240101/storage/application_security_group_types_gen.go index fca28c09311..81ea48337f7 100644 --- a/v2/api/network/v1api20240101/storage/application_security_group_types_gen.go +++ b/v2/api/network/v1api20240101/storage/application_security_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *ApplicationSecurityGroup) SetConditions(conditions conditions.Condi group.Status.Conditions = conditions } +var _ configmaps.Exporter = &ApplicationSecurityGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ApplicationSecurityGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ApplicationSecurityGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ApplicationSecurityGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ApplicationSecurityGroup{} // AzureName returns the Azure name of the resource @@ -148,9 +171,10 @@ const APIVersion_Value = APIVersion("2024-01-01") type ApplicationSecurityGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *ApplicationSecurityGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -216,6 +240,14 @@ func (group *ApplicationSecurityGroup_STATUS) ConvertStatusTo(destination genrun return destination.ConvertStatusFrom(group) } +// Storage version of v1api20240101.ApplicationSecurityGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ApplicationSecurityGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ApplicationSecurityGroup{}, &ApplicationSecurityGroupList{}) } diff --git a/v2/api/network/v1api20240101/storage/application_security_group_types_gen_test.go b/v2/api/network/v1api20240101/storage/application_security_group_types_gen_test.go index 2e429fbf39e..5a96a96916a 100644 --- a/v2/api/network/v1api20240101/storage/application_security_group_types_gen_test.go +++ b/v2/api/network/v1api20240101/storage/application_security_group_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForApplicationSecurityGroup(gens map[string]gop gens["Status"] = ApplicationSecurityGroup_STATUSGenerator() } +func Test_ApplicationSecurityGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ApplicationSecurityGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec, ApplicationSecurityGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec runs a test to see if a specific instance of ApplicationSecurityGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForApplicationSecurityGroupOperatorSpec(subject ApplicationSecurityGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ApplicationSecurityGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ApplicationSecurityGroupOperatorSpec instances for property testing - lazily instantiated by +// ApplicationSecurityGroupOperatorSpecGenerator() +var applicationSecurityGroupOperatorSpecGenerator gopter.Gen + +// ApplicationSecurityGroupOperatorSpecGenerator returns a generator of ApplicationSecurityGroupOperatorSpec instances for property testing. +func ApplicationSecurityGroupOperatorSpecGenerator() gopter.Gen { + if applicationSecurityGroupOperatorSpecGenerator != nil { + return applicationSecurityGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + applicationSecurityGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroupOperatorSpec{}), generators) + + return applicationSecurityGroupOperatorSpecGenerator +} + func Test_ApplicationSecurityGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -193,6 +248,9 @@ func RunJSONSerializationTestForApplicationSecurityGroup_Spec(subject Applicatio var applicationSecurityGroup_SpecGenerator gopter.Gen // ApplicationSecurityGroup_SpecGenerator returns a generator of ApplicationSecurityGroup_Spec instances for property testing. +// We first initialize applicationSecurityGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ApplicationSecurityGroup_SpecGenerator() gopter.Gen { if applicationSecurityGroup_SpecGenerator != nil { return applicationSecurityGroup_SpecGenerator @@ -202,6 +260,12 @@ func ApplicationSecurityGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) applicationSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) + AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec(generators) + applicationSecurityGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ApplicationSecurityGroup_Spec{}), generators) + return applicationSecurityGroup_SpecGenerator } @@ -214,3 +278,8 @@ func AddIndependentPropertyGeneratorsForApplicationSecurityGroup_Spec(gens map[s gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForApplicationSecurityGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ApplicationSecurityGroupOperatorSpecGenerator()) +} diff --git a/v2/api/network/v1api20240101/storage/structure.txt b/v2/api/network/v1api20240101/storage/structure.txt index 96870dda504..22448e70a74 100644 --- a/v2/api/network/v1api20240101/storage/structure.txt +++ b/v2/api/network/v1api20240101/storage/structure.txt @@ -5,9 +5,13 @@ APIVersion: Enum (1 value) └── "2024-01-01" ApplicationSecurityGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -25,7 +29,7 @@ ApplicationSecurityGroup: Resource └── Type: *string WebApplicationFirewallPolicy: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── CustomRules: Object (10 properties)[] │ │ ├── Action: *string @@ -81,6 +85,10 @@ WebApplicationFirewallPolicy: Resource │ │ │ ├── RuleSetType: *string │ │ │ └── RuleSetVersion: *string │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PolicySettings: *Object (13 properties) diff --git a/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen.go b/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen.go index bfb478758a5..692a19e1aa5 100644 --- a/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen.go +++ b/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *WebApplicationFirewallPolicy) SetConditions(conditions conditions. policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &WebApplicationFirewallPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *WebApplicationFirewallPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WebApplicationFirewallPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *WebApplicationFirewallPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WebApplicationFirewallPolicy{} // AzureName returns the Azure name of the resource @@ -142,11 +165,12 @@ type WebApplicationFirewallPolicyList struct { type WebApplicationFirewallPolicy_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CustomRules []WebApplicationFirewallCustomRule `json:"customRules,omitempty"` - Location *string `json:"location,omitempty"` - ManagedRules *ManagedRulesDefinition `json:"managedRules,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CustomRules []WebApplicationFirewallCustomRule `json:"customRules,omitempty"` + Location *string `json:"location,omitempty"` + ManagedRules *ManagedRulesDefinition `json:"managedRules,omitempty"` + OperatorSpec *WebApplicationFirewallPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -315,6 +339,14 @@ type WebApplicationFirewallCustomRule_STATUS struct { State *string `json:"state,omitempty"` } +// Storage version of v1api20240101.WebApplicationFirewallPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebApplicationFirewallPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20240101.GroupByUserSession // Define user session identifier group by clauses. type GroupByUserSession struct { diff --git a/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen_test.go b/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen_test.go index 34e0cab107d..7020a4912f5 100644 --- a/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen_test.go +++ b/v2/api/network/v1api20240101/storage/web_application_firewall_policy_types_gen_test.go @@ -2334,6 +2334,61 @@ func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy(gens map[string gens["Status"] = WebApplicationFirewallPolicy_STATUSGenerator() } +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebApplicationFirewallPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec runs a test to see if a specific instance of WebApplicationFirewallPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebApplicationFirewallPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing - lazily instantiated by +// WebApplicationFirewallPolicyOperatorSpecGenerator() +var webApplicationFirewallPolicyOperatorSpecGenerator gopter.Gen + +// WebApplicationFirewallPolicyOperatorSpecGenerator returns a generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing. +func WebApplicationFirewallPolicyOperatorSpecGenerator() gopter.Gen { + if webApplicationFirewallPolicyOperatorSpecGenerator != nil { + return webApplicationFirewallPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webApplicationFirewallPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebApplicationFirewallPolicyOperatorSpec{}), generators) + + return webApplicationFirewallPolicyOperatorSpecGenerator +} + func Test_WebApplicationFirewallPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2502,6 +2557,7 @@ func AddIndependentPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens m func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens map[string]gopter.Gen) { gens["CustomRules"] = gen.SliceOf(WebApplicationFirewallCustomRuleGenerator()) gens["ManagedRules"] = gen.PtrOf(ManagedRulesDefinitionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebApplicationFirewallPolicyOperatorSpecGenerator()) gens["PolicySettings"] = gen.PtrOf(PolicySettingsGenerator()) } diff --git a/v2/api/network/v1api20240101/storage/zz_generated.deepcopy.go b/v2/api/network/v1api20240101/storage/zz_generated.deepcopy.go index 5a10f7d6854..d9fda15e287 100644 --- a/v2/api/network/v1api20240101/storage/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20240101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -101,6 +102,50 @@ func (in *ApplicationSecurityGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationSecurityGroupOperatorSpec) DeepCopyInto(out *ApplicationSecurityGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSecurityGroupOperatorSpec. +func (in *ApplicationSecurityGroupOperatorSpec) DeepCopy() *ApplicationSecurityGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ApplicationSecurityGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationSecurityGroup_STATUS) DeepCopyInto(out *ApplicationSecurityGroup_STATUS) { *out = *in @@ -180,6 +225,11 @@ func (in *ApplicationSecurityGroup_Spec) DeepCopyInto(out *ApplicationSecurityGr *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApplicationSecurityGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1530,6 +1580,50 @@ func (in *WebApplicationFirewallPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopyInto(out *WebApplicationFirewallPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebApplicationFirewallPolicyOperatorSpec. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopy() *WebApplicationFirewallPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(WebApplicationFirewallPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebApplicationFirewallPolicy_STATUS) DeepCopyInto(out *WebApplicationFirewallPolicy_STATUS) { *out = *in @@ -1659,6 +1753,11 @@ func (in *WebApplicationFirewallPolicy_Spec) DeepCopyInto(out *WebApplicationFir *out = new(ManagedRulesDefinition) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebApplicationFirewallPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/network/v1api20240101/structure.txt b/v2/api/network/v1api20240101/structure.txt index 81ebe582a4b..2fd4f89f9e9 100644 --- a/v2/api/network/v1api20240101/structure.txt +++ b/v2/api/network/v1api20240101/structure.txt @@ -5,9 +5,12 @@ APIVersion: Enum (1 value) └── "2024-01-01" ApplicationSecurityGroup: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Tags: map[string]string └── Status: Object (9 properties) @@ -26,7 +29,7 @@ ApplicationSecurityGroup: Resource └── Type: *string WebApplicationFirewallPolicy: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MaxLength: 128 │ ├── CustomRules: Object (9 properties)[] @@ -133,6 +136,9 @@ WebApplicationFirewallPolicy: Resource │ │ │ └── "Enabled" │ │ ├── RuleSetType: *string │ │ └── RuleSetVersion: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PolicySettings: *Object (12 properties) │ │ ├── CustomBlockResponseBody: Validated<*string> (2 rules) diff --git a/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen.go b/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen.go index 230b182e515..a0c1130ec41 100644 --- a/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen.go +++ b/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (policy *WebApplicationFirewallPolicy) defaultAzureName() { // defaultImpl applies the code generated defaults to the WebApplicationFirewallPolicy resource func (policy *WebApplicationFirewallPolicy) defaultImpl() { policy.defaultAzureName() } +var _ configmaps.Exporter = &WebApplicationFirewallPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *WebApplicationFirewallPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WebApplicationFirewallPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *WebApplicationFirewallPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &WebApplicationFirewallPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (policy *WebApplicationFirewallPolicy) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (policy *WebApplicationFirewallPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (policy *WebApplicationFirewallPolicy) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *WebApplicationFirewallPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (policy *WebApplicationFirewallPolicy) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *WebApplicationFirewallPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *WebApplicationFirewallPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WebApplicationFirewallPolicy) @@ -341,6 +386,10 @@ type WebApplicationFirewallPolicy_Spec struct { // ManagedRules: Describes the managedRules structure. ManagedRules *ManagedRulesDefinition `json:"managedRules,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WebApplicationFirewallPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -460,6 +509,8 @@ func (policy *WebApplicationFirewallPolicy_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -581,6 +632,18 @@ func (policy *WebApplicationFirewallPolicy_Spec) AssignProperties_From_WebApplic policy.ManagedRules = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WebApplicationFirewallPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -649,6 +712,18 @@ func (policy *WebApplicationFirewallPolicy_Spec) AssignProperties_To_WebApplicat destination.ManagedRules = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.WebApplicationFirewallPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -3422,6 +3497,110 @@ func (rule *WebApplicationFirewallCustomRule_STATUS) AssignProperties_To_WebAppl return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WebApplicationFirewallPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec populates our WebApplicationFirewallPolicyOperatorSpec from the provided source WebApplicationFirewallPolicyOperatorSpec +func (operator *WebApplicationFirewallPolicyOperatorSpec) AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(source *storage.WebApplicationFirewallPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec populates the provided destination WebApplicationFirewallPolicyOperatorSpec from our WebApplicationFirewallPolicyOperatorSpec +func (operator *WebApplicationFirewallPolicyOperatorSpec) AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(destination *storage.WebApplicationFirewallPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type WebApplicationFirewallPolicyPropertiesFormat_ResourceState_STATUS string const ( diff --git a/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen_test.go b/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen_test.go index 697ddffcd2c..c371ef44546 100644 --- a/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen_test.go +++ b/v2/api/network/v1api20240101/web_application_firewall_policy_types_gen_test.go @@ -3864,6 +3864,103 @@ func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy(gens map[string gens["Status"] = WebApplicationFirewallPolicy_STATUSGenerator() } +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WebApplicationFirewallPolicyOperatorSpec to WebApplicationFirewallPolicyOperatorSpec via AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec & AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec tests if a specific instance of WebApplicationFirewallPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WebApplicationFirewallPolicyOperatorSpec + err := copied.AssignProperties_To_WebApplicationFirewallPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WebApplicationFirewallPolicyOperatorSpec + err = actual.AssignProperties_From_WebApplicationFirewallPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WebApplicationFirewallPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WebApplicationFirewallPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec, WebApplicationFirewallPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec runs a test to see if a specific instance of WebApplicationFirewallPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWebApplicationFirewallPolicyOperatorSpec(subject WebApplicationFirewallPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WebApplicationFirewallPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing - lazily instantiated by +// WebApplicationFirewallPolicyOperatorSpecGenerator() +var webApplicationFirewallPolicyOperatorSpecGenerator gopter.Gen + +// WebApplicationFirewallPolicyOperatorSpecGenerator returns a generator of WebApplicationFirewallPolicyOperatorSpec instances for property testing. +func WebApplicationFirewallPolicyOperatorSpecGenerator() gopter.Gen { + if webApplicationFirewallPolicyOperatorSpecGenerator != nil { + return webApplicationFirewallPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + webApplicationFirewallPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WebApplicationFirewallPolicyOperatorSpec{}), generators) + + return webApplicationFirewallPolicyOperatorSpecGenerator +} + func Test_WebApplicationFirewallPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -4125,6 +4222,7 @@ func AddIndependentPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens m func AddRelatedPropertyGeneratorsForWebApplicationFirewallPolicy_Spec(gens map[string]gopter.Gen) { gens["CustomRules"] = gen.SliceOf(WebApplicationFirewallCustomRuleGenerator()) gens["ManagedRules"] = gen.PtrOf(ManagedRulesDefinitionGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WebApplicationFirewallPolicyOperatorSpecGenerator()) gens["PolicySettings"] = gen.PtrOf(PolicySettingsGenerator()) } diff --git a/v2/api/network/v1api20240101/zz_generated.deepcopy.go b/v2/api/network/v1api20240101/zz_generated.deepcopy.go index a116ce9dbd8..73108761ad5 100644 --- a/v2/api/network/v1api20240101/zz_generated.deepcopy.go +++ b/v2/api/network/v1api20240101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20240101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -94,6 +95,43 @@ func (in *ApplicationSecurityGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationSecurityGroupOperatorSpec) DeepCopyInto(out *ApplicationSecurityGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSecurityGroupOperatorSpec. +func (in *ApplicationSecurityGroupOperatorSpec) DeepCopy() *ApplicationSecurityGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ApplicationSecurityGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationSecurityGroup_STATUS) DeepCopyInto(out *ApplicationSecurityGroup_STATUS) { *out = *in @@ -166,6 +204,11 @@ func (in *ApplicationSecurityGroup_Spec) DeepCopyInto(out *ApplicationSecurityGr *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ApplicationSecurityGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1292,6 +1335,43 @@ func (in *WebApplicationFirewallPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopyInto(out *WebApplicationFirewallPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebApplicationFirewallPolicyOperatorSpec. +func (in *WebApplicationFirewallPolicyOperatorSpec) DeepCopy() *WebApplicationFirewallPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(WebApplicationFirewallPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebApplicationFirewallPolicy_STATUS) DeepCopyInto(out *WebApplicationFirewallPolicy_STATUS) { *out = *in @@ -1414,6 +1494,11 @@ func (in *WebApplicationFirewallPolicy_Spec) DeepCopyInto(out *WebApplicationFir *out = new(ManagedRulesDefinition) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WebApplicationFirewallPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/operationalinsights/v1api20210601/storage/structure.txt b/v2/api/operationalinsights/v1api20210601/storage/structure.txt index f714476dd22..d9a66c8ffbb 100644 --- a/v2/api/operationalinsights/v1api20210601/storage/structure.txt +++ b/v2/api/operationalinsights/v1api20210601/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-06-01" Workspace: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AzureName: string │ ├── Etag: *string │ ├── Features: *Object (6 properties) @@ -17,6 +17,10 @@ Workspace: Resource │ │ └── PropertyBag: genruntime.PropertyBag │ ├── ForceCmkForQuery: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen.go b/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen.go index 44dfc0e03ab..6a0512553fd 100644 --- a/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen.go +++ b/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (workspace *Workspace) SetConditions(conditions conditions.Conditions) { workspace.Status.Conditions = conditions } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Workspace{} // AzureName returns the Azure name of the resource @@ -148,12 +171,13 @@ const APIVersion_Value = APIVersion("2021-06-01") type Workspace_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Etag *string `json:"etag,omitempty"` - Features *WorkspaceFeatures `json:"features,omitempty"` - ForceCmkForQuery *bool `json:"forceCmkForQuery,omitempty"` - Location *string `json:"location,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Etag *string `json:"etag,omitempty"` + Features *WorkspaceFeatures `json:"features,omitempty"` + ForceCmkForQuery *bool `json:"forceCmkForQuery,omitempty"` + Location *string `json:"location,omitempty"` + OperatorSpec *WorkspaceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -282,6 +306,14 @@ type WorkspaceFeatures_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20210601.WorkspaceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspaceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210601.WorkspaceSku // The SKU (tier) of a workspace. type WorkspaceSku struct { diff --git a/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen_test.go b/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen_test.go index d84ec4cb236..405cb04ef42 100644 --- a/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen_test.go +++ b/v2/api/operationalinsights/v1api20210601/storage/workspace_types_gen_test.go @@ -391,6 +391,61 @@ func AddIndependentPropertyGeneratorsForWorkspaceFeatures_STATUS(gens map[string gens["ImmediatePurgeDataOn30Days"] = gen.PtrOf(gen.Bool()) } +func Test_WorkspaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspaceOperatorSpec runs a test to see if a specific instance of WorkspaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspaceOperatorSpec instances for property testing - lazily instantiated by +// WorkspaceOperatorSpecGenerator() +var workspaceOperatorSpecGenerator gopter.Gen + +// WorkspaceOperatorSpecGenerator returns a generator of WorkspaceOperatorSpec instances for property testing. +func WorkspaceOperatorSpecGenerator() gopter.Gen { + if workspaceOperatorSpecGenerator != nil { + return workspaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspaceOperatorSpec{}), generators) + + return workspaceOperatorSpecGenerator +} + func Test_WorkspaceSku_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -690,6 +745,7 @@ func AddIndependentPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Ge // AddRelatedPropertyGeneratorsForWorkspace_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Gen) { gens["Features"] = gen.PtrOf(WorkspaceFeaturesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspaceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(WorkspaceSkuGenerator()) gens["WorkspaceCapping"] = gen.PtrOf(WorkspaceCappingGenerator()) } diff --git a/v2/api/operationalinsights/v1api20210601/storage/zz_generated.deepcopy.go b/v2/api/operationalinsights/v1api20210601/storage/zz_generated.deepcopy.go index b4ce481f497..9ff444d81df 100644 --- a/v2/api/operationalinsights/v1api20210601/storage/zz_generated.deepcopy.go +++ b/v2/api/operationalinsights/v1api20210601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -264,6 +265,50 @@ func (in *WorkspaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceOperatorSpec. +func (in *WorkspaceOperatorSpec) DeepCopy() *WorkspaceOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceSku) DeepCopyInto(out *WorkspaceSku) { *out = *in @@ -479,6 +524,11 @@ func (in *Workspace_Spec) DeepCopyInto(out *Workspace_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/operationalinsights/v1api20210601/structure.txt b/v2/api/operationalinsights/v1api20210601/structure.txt index 785e9eb9cfa..88a582d0494 100644 --- a/v2/api/operationalinsights/v1api20210601/structure.txt +++ b/v2/api/operationalinsights/v1api20210601/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-06-01" Workspace: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ ├── Rule 1: MinLength: 4 @@ -19,6 +19,9 @@ Workspace: Resource │ │ └── ImmediatePurgeDataOn30Days: *bool │ ├── ForceCmkForQuery: *bool │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProvisioningState: *Enum (7 values) │ │ ├── "Canceled" diff --git a/v2/api/operationalinsights/v1api20210601/workspace_types_gen.go b/v2/api/operationalinsights/v1api20210601/workspace_types_gen.go index 7cdcbc3a2b6..567422c7f81 100644 --- a/v2/api/operationalinsights/v1api20210601/workspace_types_gen.go +++ b/v2/api/operationalinsights/v1api20210601/workspace_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (workspace *Workspace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Workspace resource func (workspace *Workspace) defaultImpl() { workspace.defaultAzureName() } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Workspace{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (workspace *Workspace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (workspace *Workspace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference} + return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations, workspace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (workspace *Workspace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return workspace.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (workspace *Workspace) validateConfigMapDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (workspace *Workspace) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (workspace *Workspace) validateSecretDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (workspace *Workspace) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Workspace) @@ -351,6 +396,10 @@ type Workspace_Spec struct { // Location: The geo-location where the resource lives Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspaceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -526,6 +575,8 @@ func (workspace *Workspace_Spec) PopulateFromARM(owner genruntime.ArbitraryOwner workspace.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": workspace.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -696,6 +747,18 @@ func (workspace *Workspace_Spec) AssignProperties_From_Workspace_Spec(source *st // Location workspace.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspaceOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspaceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspaceOperatorSpec() to populate field OperatorSpec") + } + workspace.OperatorSpec = &operatorSpec + } else { + workspace.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -799,6 +862,18 @@ func (workspace *Workspace_Spec) AssignProperties_To_Workspace_Spec(destination // Location destination.Location = genruntime.ClonePointerToString(workspace.Location) + // OperatorSpec + if workspace.OperatorSpec != nil { + var operatorSpec storage.WorkspaceOperatorSpec + err := workspace.OperatorSpec.AssignProperties_To_WorkspaceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspaceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = workspace.OriginalVersion() @@ -2265,6 +2340,110 @@ func (features *WorkspaceFeatures_STATUS) AssignProperties_To_WorkspaceFeatures_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspaceOperatorSpec populates our WorkspaceOperatorSpec from the provided source WorkspaceOperatorSpec +func (operator *WorkspaceOperatorSpec) AssignProperties_From_WorkspaceOperatorSpec(source *storage.WorkspaceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspaceOperatorSpec populates the provided destination WorkspaceOperatorSpec from our WorkspaceOperatorSpec +func (operator *WorkspaceOperatorSpec) AssignProperties_To_WorkspaceOperatorSpec(destination *storage.WorkspaceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Canceled","Creating","Deleting","Failed","ProvisioningAccount","Succeeded","Updating"} type WorkspaceProperties_ProvisioningState string diff --git a/v2/api/operationalinsights/v1api20210601/workspace_types_gen_test.go b/v2/api/operationalinsights/v1api20210601/workspace_types_gen_test.go index 58972539113..c631e879e58 100644 --- a/v2/api/operationalinsights/v1api20210601/workspace_types_gen_test.go +++ b/v2/api/operationalinsights/v1api20210601/workspace_types_gen_test.go @@ -693,6 +693,103 @@ func AddIndependentPropertyGeneratorsForWorkspaceFeatures_STATUS(gens map[string gens["ImmediatePurgeDataOn30Days"] = gen.PtrOf(gen.Bool()) } +func Test_WorkspaceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspaceOperatorSpec to WorkspaceOperatorSpec via AssignProperties_To_WorkspaceOperatorSpec & AssignProperties_From_WorkspaceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspaceOperatorSpec tests if a specific instance of WorkspaceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspaceOperatorSpec + err := copied.AssignProperties_To_WorkspaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspaceOperatorSpec + err = actual.AssignProperties_From_WorkspaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspaceOperatorSpec runs a test to see if a specific instance of WorkspaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspaceOperatorSpec instances for property testing - lazily instantiated by +// WorkspaceOperatorSpecGenerator() +var workspaceOperatorSpecGenerator gopter.Gen + +// WorkspaceOperatorSpecGenerator returns a generator of WorkspaceOperatorSpec instances for property testing. +func WorkspaceOperatorSpecGenerator() gopter.Gen { + if workspaceOperatorSpecGenerator != nil { + return workspaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspaceOperatorSpec{}), generators) + + return workspaceOperatorSpecGenerator +} + func Test_WorkspaceSku_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1205,6 +1302,7 @@ func AddIndependentPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Ge // AddRelatedPropertyGeneratorsForWorkspace_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Gen) { gens["Features"] = gen.PtrOf(WorkspaceFeaturesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspaceOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(WorkspaceSkuGenerator()) gens["WorkspaceCapping"] = gen.PtrOf(WorkspaceCappingGenerator()) } diff --git a/v2/api/operationalinsights/v1api20210601/zz_generated.deepcopy.go b/v2/api/operationalinsights/v1api20210601/zz_generated.deepcopy.go index 839bb9061d8..a23a2efba53 100644 --- a/v2/api/operationalinsights/v1api20210601/zz_generated.deepcopy.go +++ b/v2/api/operationalinsights/v1api20210601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -229,6 +230,43 @@ func (in *WorkspaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceOperatorSpec. +func (in *WorkspaceOperatorSpec) DeepCopy() *WorkspaceOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceSku) DeepCopyInto(out *WorkspaceSku) { *out = *in @@ -423,6 +461,11 @@ func (in *Workspace_Spec) DeepCopyInto(out *Workspace_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen.go b/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen.go index 39ecb891fb0..e4888dccc8d 100644 --- a/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen.go +++ b/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -92,6 +94,26 @@ func (cluster *OpenShiftCluster) defaultAzureName() { // defaultImpl applies the code generated defaults to the OpenShiftCluster resource func (cluster *OpenShiftCluster) defaultImpl() { cluster.defaultAzureName() } +var _ configmaps.Exporter = &OpenShiftCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *OpenShiftCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &OpenShiftCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *OpenShiftCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &OpenShiftCluster{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (cluster *OpenShiftCluster) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (cluster *OpenShiftCluster) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){cluster.validateResourceReferences, cluster.validateOwnerReference, cluster.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){cluster.validateResourceReferences, cluster.validateOwnerReference, cluster.validateSecretDestinations, cluster.validateConfigMapDestinations, cluster.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -228,12 +250,26 @@ func (cluster *OpenShiftCluster) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return cluster.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return cluster.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return cluster.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return cluster.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (cluster *OpenShiftCluster) validateConfigMapDestinations() (admission.Warnings, error) { + if cluster.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(cluster, nil, cluster.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (cluster *OpenShiftCluster) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&cluster.Spec) @@ -257,6 +293,14 @@ func (cluster *OpenShiftCluster) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (cluster *OpenShiftCluster) validateSecretDestinations() (admission.Warnings, error) { + if cluster.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(cluster, nil, cluster.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (cluster *OpenShiftCluster) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*OpenShiftCluster) @@ -367,6 +411,10 @@ type OpenShiftCluster_Spec struct { // NetworkProfile: The cluster network profile. NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *OpenShiftClusterOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -566,6 +614,8 @@ func (cluster *OpenShiftCluster_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": cluster.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -736,6 +786,18 @@ func (cluster *OpenShiftCluster_Spec) AssignProperties_From_OpenShiftCluster_Spe cluster.NetworkProfile = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec OpenShiftClusterOperatorSpec + err := operatorSpec.AssignProperties_From_OpenShiftClusterOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_OpenShiftClusterOperatorSpec() to populate field OperatorSpec") + } + cluster.OperatorSpec = &operatorSpec + } else { + cluster.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -858,6 +920,18 @@ func (cluster *OpenShiftCluster_Spec) AssignProperties_To_OpenShiftCluster_Spec( destination.NetworkProfile = nil } + // OperatorSpec + if cluster.OperatorSpec != nil { + var operatorSpec storage.OpenShiftClusterOperatorSpec + err := cluster.OperatorSpec.AssignProperties_To_OpenShiftClusterOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_OpenShiftClusterOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = cluster.OriginalVersion() @@ -3250,6 +3324,110 @@ func (profile *NetworkProfile_STATUS) AssignProperties_To_NetworkProfile_STATUS( return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type OpenShiftClusterOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_OpenShiftClusterOperatorSpec populates our OpenShiftClusterOperatorSpec from the provided source OpenShiftClusterOperatorSpec +func (operator *OpenShiftClusterOperatorSpec) AssignProperties_From_OpenShiftClusterOperatorSpec(source *storage.OpenShiftClusterOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_OpenShiftClusterOperatorSpec populates the provided destination OpenShiftClusterOperatorSpec from our OpenShiftClusterOperatorSpec +func (operator *OpenShiftClusterOperatorSpec) AssignProperties_To_OpenShiftClusterOperatorSpec(destination *storage.OpenShiftClusterOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // ProvisioningState represents a provisioning state. type ProvisioningState_STATUS string diff --git a/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen_test.go b/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen_test.go index 503c79d948a..909db2319bb 100644 --- a/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen_test.go +++ b/v2/api/redhatopenshift/v1api20231122/open_shift_cluster_types_gen_test.go @@ -1856,6 +1856,103 @@ func AddRelatedPropertyGeneratorsForOpenShiftCluster(gens map[string]gopter.Gen) gens["Status"] = OpenShiftCluster_STATUSGenerator() } +func Test_OpenShiftClusterOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from OpenShiftClusterOperatorSpec to OpenShiftClusterOperatorSpec via AssignProperties_To_OpenShiftClusterOperatorSpec & AssignProperties_From_OpenShiftClusterOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForOpenShiftClusterOperatorSpec, OpenShiftClusterOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForOpenShiftClusterOperatorSpec tests if a specific instance of OpenShiftClusterOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForOpenShiftClusterOperatorSpec(subject OpenShiftClusterOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.OpenShiftClusterOperatorSpec + err := copied.AssignProperties_To_OpenShiftClusterOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual OpenShiftClusterOperatorSpec + err = actual.AssignProperties_From_OpenShiftClusterOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_OpenShiftClusterOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of OpenShiftClusterOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForOpenShiftClusterOperatorSpec, OpenShiftClusterOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForOpenShiftClusterOperatorSpec runs a test to see if a specific instance of OpenShiftClusterOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForOpenShiftClusterOperatorSpec(subject OpenShiftClusterOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual OpenShiftClusterOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of OpenShiftClusterOperatorSpec instances for property testing - lazily instantiated by +// OpenShiftClusterOperatorSpecGenerator() +var openShiftClusterOperatorSpecGenerator gopter.Gen + +// OpenShiftClusterOperatorSpecGenerator returns a generator of OpenShiftClusterOperatorSpec instances for property testing. +func OpenShiftClusterOperatorSpecGenerator() gopter.Gen { + if openShiftClusterOperatorSpecGenerator != nil { + return openShiftClusterOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + openShiftClusterOperatorSpecGenerator = gen.Struct(reflect.TypeOf(OpenShiftClusterOperatorSpec{}), generators) + + return openShiftClusterOperatorSpecGenerator +} + func Test_OpenShiftCluster_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2119,6 +2216,7 @@ func AddRelatedPropertyGeneratorsForOpenShiftCluster_Spec(gens map[string]gopter gens["IngressProfiles"] = gen.SliceOf(IngressProfileGenerator()) gens["MasterProfile"] = gen.PtrOf(MasterProfileGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(OpenShiftClusterOperatorSpecGenerator()) gens["ServicePrincipalProfile"] = gen.PtrOf(ServicePrincipalProfileGenerator()) gens["WorkerProfiles"] = gen.SliceOf(WorkerProfileGenerator()) } diff --git a/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen.go b/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen.go index 807f31d176e..8710f3cdbfa 100644 --- a/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen.go +++ b/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (cluster *OpenShiftCluster) SetConditions(conditions conditions.Conditions) cluster.Status.Conditions = conditions } +var _ configmaps.Exporter = &OpenShiftCluster{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (cluster *OpenShiftCluster) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &OpenShiftCluster{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (cluster *OpenShiftCluster) SecretDestinationExpressions() []*core.DestinationExpression { + if cluster.Spec.OperatorSpec == nil { + return nil + } + return cluster.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &OpenShiftCluster{} // AzureName returns the Azure name of the resource @@ -150,13 +173,14 @@ type OpenShiftCluster_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClusterProfile *ClusterProfile `json:"clusterProfile,omitempty"` - IngressProfiles []IngressProfile `json:"ingressProfiles,omitempty"` - Location *string `json:"location,omitempty"` - MasterProfile *MasterProfile `json:"masterProfile,omitempty"` - NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClusterProfile *ClusterProfile `json:"clusterProfile,omitempty"` + IngressProfiles []IngressProfile `json:"ingressProfiles,omitempty"` + Location *string `json:"location,omitempty"` + MasterProfile *MasterProfile `json:"masterProfile,omitempty"` + NetworkProfile *NetworkProfile `json:"networkProfile,omitempty"` + OperatorSpec *OpenShiftClusterOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -338,6 +362,14 @@ type NetworkProfile_STATUS struct { ServiceCidr *string `json:"serviceCidr,omitempty"` } +// Storage version of v1api20231122.OpenShiftClusterOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type OpenShiftClusterOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20231122.ServicePrincipalProfile // ServicePrincipalProfile represents a service principal profile. type ServicePrincipalProfile struct { diff --git a/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen_test.go b/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen_test.go index d17eabf55ac..2e35d0d7ee0 100644 --- a/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen_test.go +++ b/v2/api/redhatopenshift/v1api20231122/storage/open_shift_cluster_types_gen_test.go @@ -1098,6 +1098,61 @@ func AddRelatedPropertyGeneratorsForOpenShiftCluster(gens map[string]gopter.Gen) gens["Status"] = OpenShiftCluster_STATUSGenerator() } +func Test_OpenShiftClusterOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of OpenShiftClusterOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForOpenShiftClusterOperatorSpec, OpenShiftClusterOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForOpenShiftClusterOperatorSpec runs a test to see if a specific instance of OpenShiftClusterOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForOpenShiftClusterOperatorSpec(subject OpenShiftClusterOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual OpenShiftClusterOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of OpenShiftClusterOperatorSpec instances for property testing - lazily instantiated by +// OpenShiftClusterOperatorSpecGenerator() +var openShiftClusterOperatorSpecGenerator gopter.Gen + +// OpenShiftClusterOperatorSpecGenerator returns a generator of OpenShiftClusterOperatorSpec instances for property testing. +func OpenShiftClusterOperatorSpecGenerator() gopter.Gen { + if openShiftClusterOperatorSpecGenerator != nil { + return openShiftClusterOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + openShiftClusterOperatorSpecGenerator = gen.Struct(reflect.TypeOf(OpenShiftClusterOperatorSpec{}), generators) + + return openShiftClusterOperatorSpecGenerator +} + func Test_OpenShiftCluster_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1271,6 +1326,7 @@ func AddRelatedPropertyGeneratorsForOpenShiftCluster_Spec(gens map[string]gopter gens["IngressProfiles"] = gen.SliceOf(IngressProfileGenerator()) gens["MasterProfile"] = gen.PtrOf(MasterProfileGenerator()) gens["NetworkProfile"] = gen.PtrOf(NetworkProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(OpenShiftClusterOperatorSpecGenerator()) gens["ServicePrincipalProfile"] = gen.PtrOf(ServicePrincipalProfileGenerator()) gens["WorkerProfiles"] = gen.SliceOf(WorkerProfileGenerator()) } diff --git a/v2/api/redhatopenshift/v1api20231122/storage/structure.txt b/v2/api/redhatopenshift/v1api20231122/storage/structure.txt index 5dd53222153..c20a6f402c6 100644 --- a/v2/api/redhatopenshift/v1api20231122/storage/structure.txt +++ b/v2/api/redhatopenshift/v1api20231122/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-11-22" OpenShiftCluster: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── ApiserverProfile: *Object (2 properties) │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Visibility: *string @@ -39,6 +39,10 @@ OpenShiftCluster: Resource │ │ ├── PreconfiguredNSG: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── ServiceCidr: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/redhatopenshift/v1api20231122/storage/zz_generated.deepcopy.go b/v2/api/redhatopenshift/v1api20231122/storage/zz_generated.deepcopy.go index 9bd58c4ea1a..a08e26fca2a 100644 --- a/v2/api/redhatopenshift/v1api20231122/storage/zz_generated.deepcopy.go +++ b/v2/api/redhatopenshift/v1api20231122/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -643,6 +644,50 @@ func (in *OpenShiftClusterList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftClusterOperatorSpec) DeepCopyInto(out *OpenShiftClusterOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftClusterOperatorSpec. +func (in *OpenShiftClusterOperatorSpec) DeepCopy() *OpenShiftClusterOperatorSpec { + if in == nil { + return nil + } + out := new(OpenShiftClusterOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenShiftCluster_STATUS) DeepCopyInto(out *OpenShiftCluster_STATUS) { *out = *in @@ -795,6 +840,11 @@ func (in *OpenShiftCluster_Spec) DeepCopyInto(out *OpenShiftCluster_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(OpenShiftClusterOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/redhatopenshift/v1api20231122/structure.txt b/v2/api/redhatopenshift/v1api20231122/structure.txt index 35a76d23743..13e41ed6889 100644 --- a/v2/api/redhatopenshift/v1api20231122/structure.txt +++ b/v2/api/redhatopenshift/v1api20231122/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2023-11-22" OpenShiftCluster: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── ApiserverProfile: *Object (1 property) │ │ └── Visibility: *Enum (2 values) │ │ ├── "Private" @@ -44,6 +44,9 @@ OpenShiftCluster: Resource │ │ │ ├── "Disabled" │ │ │ └── "Enabled" │ │ └── ServiceCidr: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ServicePrincipalProfile: *Object (3 properties) │ │ ├── ClientId: *string diff --git a/v2/api/redhatopenshift/v1api20231122/zz_generated.deepcopy.go b/v2/api/redhatopenshift/v1api20231122/zz_generated.deepcopy.go index 5ecb506d2b8..0b53b3df14f 100644 --- a/v2/api/redhatopenshift/v1api20231122/zz_generated.deepcopy.go +++ b/v2/api/redhatopenshift/v1api20231122/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20231122 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -531,6 +532,43 @@ func (in *OpenShiftClusterList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftClusterOperatorSpec) DeepCopyInto(out *OpenShiftClusterOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftClusterOperatorSpec. +func (in *OpenShiftClusterOperatorSpec) DeepCopy() *OpenShiftClusterOperatorSpec { + if in == nil { + return nil + } + out := new(OpenShiftClusterOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenShiftCluster_STATUS) DeepCopyInto(out *OpenShiftCluster_STATUS) { *out = *in @@ -676,6 +714,11 @@ func (in *OpenShiftCluster_Spec) DeepCopyInto(out *OpenShiftCluster_Spec) { *out = new(NetworkProfile) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(OpenShiftClusterOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/resources/v1api20200601/resource_group_types_gen.go b/v2/api/resources/v1api20200601/resource_group_types_gen.go index d553f2b7a64..cddf98aee3b 100644 --- a/v2/api/resources/v1api20200601/resource_group_types_gen.go +++ b/v2/api/resources/v1api20200601/resource_group_types_gen.go @@ -9,6 +9,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -90,6 +93,26 @@ func (group *ResourceGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the ResourceGroup resource func (group *ResourceGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &ResourceGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ResourceGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ResourceGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ResourceGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ResourceGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -218,7 +241,7 @@ func (group *ResourceGroup) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (group *ResourceGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -232,7 +255,22 @@ func (group *ResourceGroup) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return group.validateResourceReferences() }, - group.validateWriteOnceProperties} + group.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *ResourceGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -244,6 +282,14 @@ func (group *ResourceGroup) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *ResourceGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *ResourceGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ResourceGroup) @@ -345,6 +391,10 @@ type ResourceGroup_Spec struct { // ManagedBy: The ID of the resource that manages this resource group. ManagedBy *string `json:"managedBy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ResourceGroupOperatorSpec `json:"operatorSpec,omitempty"` + // Tags: The tags attached to the resource group. Tags map[string]string `json:"tags,omitempty"` } @@ -410,6 +460,8 @@ func (group *ResourceGroup_Spec) PopulateFromARM(owner genruntime.ArbitraryOwner group.ManagedBy = &managedBy } + // no assignment for property "OperatorSpec" + // Set property "Tags": if typedInput.Tags != nil { group.Tags = make(map[string]string, len(typedInput.Tags)) @@ -484,6 +536,18 @@ func (group *ResourceGroup_Spec) AssignProperties_From_ResourceGroup_Spec(source // ManagedBy group.ManagedBy = genruntime.ClonePointerToString(source.ManagedBy) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ResourceGroupOperatorSpec + err := operatorSpec.AssignProperties_From_ResourceGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ResourceGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Tags group.Tags = genruntime.CloneMapOfStringToString(source.Tags) @@ -505,6 +569,18 @@ func (group *ResourceGroup_Spec) AssignProperties_To_ResourceGroup_Spec(destinat // ManagedBy destination.ManagedBy = genruntime.ClonePointerToString(group.ManagedBy) + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.ResourceGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_ResourceGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ResourceGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -782,6 +858,110 @@ func (group *ResourceGroup_STATUS) AssignProperties_To_ResourceGroup_STATUS(dest return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ResourceGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ResourceGroupOperatorSpec populates our ResourceGroupOperatorSpec from the provided source ResourceGroupOperatorSpec +func (operator *ResourceGroupOperatorSpec) AssignProperties_From_ResourceGroupOperatorSpec(source *storage.ResourceGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ResourceGroupOperatorSpec populates the provided destination ResourceGroupOperatorSpec from our ResourceGroupOperatorSpec +func (operator *ResourceGroupOperatorSpec) AssignProperties_To_ResourceGroupOperatorSpec(destination *storage.ResourceGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The resource group properties. type ResourceGroupProperties_STATUS struct { // ProvisioningState: The provisioning state. diff --git a/v2/api/resources/v1api20200601/resource_group_types_gen_test.go b/v2/api/resources/v1api20200601/resource_group_types_gen_test.go index 9a46e33eba4..4cf2661f59e 100644 --- a/v2/api/resources/v1api20200601/resource_group_types_gen_test.go +++ b/v2/api/resources/v1api20200601/resource_group_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForResourceGroup(gens map[string]gopter.Gen) { gens["Status"] = ResourceGroup_STATUSGenerator() } +func Test_ResourceGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ResourceGroupOperatorSpec to ResourceGroupOperatorSpec via AssignProperties_To_ResourceGroupOperatorSpec & AssignProperties_From_ResourceGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForResourceGroupOperatorSpec, ResourceGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForResourceGroupOperatorSpec tests if a specific instance of ResourceGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForResourceGroupOperatorSpec(subject ResourceGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ResourceGroupOperatorSpec + err := copied.AssignProperties_To_ResourceGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ResourceGroupOperatorSpec + err = actual.AssignProperties_From_ResourceGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ResourceGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ResourceGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForResourceGroupOperatorSpec, ResourceGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForResourceGroupOperatorSpec runs a test to see if a specific instance of ResourceGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForResourceGroupOperatorSpec(subject ResourceGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ResourceGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ResourceGroupOperatorSpec instances for property testing - lazily instantiated by +// ResourceGroupOperatorSpecGenerator() +var resourceGroupOperatorSpecGenerator gopter.Gen + +// ResourceGroupOperatorSpecGenerator returns a generator of ResourceGroupOperatorSpec instances for property testing. +func ResourceGroupOperatorSpecGenerator() gopter.Gen { + if resourceGroupOperatorSpecGenerator != nil { + return resourceGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + resourceGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroupOperatorSpec{}), generators) + + return resourceGroupOperatorSpecGenerator +} + func Test_ResourceGroupProperties_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -476,6 +573,9 @@ func RunJSONSerializationTestForResourceGroup_Spec(subject ResourceGroup_Spec) s var resourceGroup_SpecGenerator gopter.Gen // ResourceGroup_SpecGenerator returns a generator of ResourceGroup_Spec instances for property testing. +// We first initialize resourceGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ResourceGroup_SpecGenerator() gopter.Gen { if resourceGroup_SpecGenerator != nil { return resourceGroup_SpecGenerator @@ -485,6 +585,12 @@ func ResourceGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForResourceGroup_Spec(generators) resourceGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForResourceGroup_Spec(generators) + AddRelatedPropertyGeneratorsForResourceGroup_Spec(generators) + resourceGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroup_Spec{}), generators) + return resourceGroup_SpecGenerator } @@ -497,3 +603,8 @@ func AddIndependentPropertyGeneratorsForResourceGroup_Spec(gens map[string]gopte gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForResourceGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForResourceGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ResourceGroupOperatorSpecGenerator()) +} diff --git a/v2/api/resources/v1api20200601/storage/resource_group_types_gen.go b/v2/api/resources/v1api20200601/storage/resource_group_types_gen.go index 23b2b54e58b..845e15c7ace 100644 --- a/v2/api/resources/v1api20200601/storage/resource_group_types_gen.go +++ b/v2/api/resources/v1api20200601/storage/resource_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *ResourceGroup) SetConditions(conditions conditions.Conditions) { group.Status.Conditions = conditions } +var _ configmaps.Exporter = &ResourceGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ResourceGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ResourceGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ResourceGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ResourceGroup{} // AzureName returns the Azure name of the resource @@ -158,12 +181,13 @@ const APIVersion_Value = APIVersion("2020-06-01") type ResourceGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Location *string `json:"location,omitempty"` - ManagedBy *string `json:"managedBy,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Tags map[string]string `json:"tags,omitempty"` + AzureName string `json:"azureName,omitempty"` + Location *string `json:"location,omitempty"` + ManagedBy *string `json:"managedBy,omitempty"` + OperatorSpec *ResourceGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + Tags map[string]string `json:"tags,omitempty"` } var _ genruntime.ConvertibleSpec = &ResourceGroup_Spec{} @@ -220,6 +244,14 @@ func (group *ResourceGroup_STATUS) ConvertStatusTo(destination genruntime.Conver return destination.ConvertStatusFrom(group) } +// Storage version of v1api20200601.ResourceGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ResourceGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20200601.ResourceGroupProperties_STATUS // The resource group properties. type ResourceGroupProperties_STATUS struct { diff --git a/v2/api/resources/v1api20200601/storage/resource_group_types_gen_test.go b/v2/api/resources/v1api20200601/storage/resource_group_types_gen_test.go index 180b1396456..cf068b5fa21 100644 --- a/v2/api/resources/v1api20200601/storage/resource_group_types_gen_test.go +++ b/v2/api/resources/v1api20200601/storage/resource_group_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForResourceGroup(gens map[string]gopter.Gen) { gens["Status"] = ResourceGroup_STATUSGenerator() } +func Test_ResourceGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ResourceGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForResourceGroupOperatorSpec, ResourceGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForResourceGroupOperatorSpec runs a test to see if a specific instance of ResourceGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForResourceGroupOperatorSpec(subject ResourceGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ResourceGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ResourceGroupOperatorSpec instances for property testing - lazily instantiated by +// ResourceGroupOperatorSpecGenerator() +var resourceGroupOperatorSpecGenerator gopter.Gen + +// ResourceGroupOperatorSpecGenerator returns a generator of ResourceGroupOperatorSpec instances for property testing. +func ResourceGroupOperatorSpecGenerator() gopter.Gen { + if resourceGroupOperatorSpecGenerator != nil { + return resourceGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + resourceGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroupOperatorSpec{}), generators) + + return resourceGroupOperatorSpecGenerator +} + func Test_ResourceGroupProperties_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -264,6 +319,9 @@ func RunJSONSerializationTestForResourceGroup_Spec(subject ResourceGroup_Spec) s var resourceGroup_SpecGenerator gopter.Gen // ResourceGroup_SpecGenerator returns a generator of ResourceGroup_Spec instances for property testing. +// We first initialize resourceGroup_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ResourceGroup_SpecGenerator() gopter.Gen { if resourceGroup_SpecGenerator != nil { return resourceGroup_SpecGenerator @@ -273,6 +331,12 @@ func ResourceGroup_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForResourceGroup_Spec(generators) resourceGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroup_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForResourceGroup_Spec(generators) + AddRelatedPropertyGeneratorsForResourceGroup_Spec(generators) + resourceGroup_SpecGenerator = gen.Struct(reflect.TypeOf(ResourceGroup_Spec{}), generators) + return resourceGroup_SpecGenerator } @@ -286,3 +350,8 @@ func AddIndependentPropertyGeneratorsForResourceGroup_Spec(gens map[string]gopte gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForResourceGroup_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForResourceGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ResourceGroupOperatorSpecGenerator()) +} diff --git a/v2/api/resources/v1api20200601/storage/structure.txt b/v2/api/resources/v1api20200601/storage/structure.txt index 99ece438ee5..c3604483649 100644 --- a/v2/api/resources/v1api20200601/storage/structure.txt +++ b/v2/api/resources/v1api20200601/storage/structure.txt @@ -4,10 +4,14 @@ github.com/Azure/azure-service-operator/v2/api/resources/v1api20200601/storage APIVersion: Enum (1 value) └── "2020-06-01" ResourceGroup: Resource -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── Location: *string │ ├── ManagedBy: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── PropertyBag: genruntime.PropertyBag │ └── Tags: map[string]string diff --git a/v2/api/resources/v1api20200601/storage/zz_generated.deepcopy.go b/v2/api/resources/v1api20200601/storage/zz_generated.deepcopy.go index 1c8481ab7f4..41772c303a6 100644 --- a/v2/api/resources/v1api20200601/storage/zz_generated.deepcopy.go +++ b/v2/api/resources/v1api20200601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *ResourceGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceGroupOperatorSpec) DeepCopyInto(out *ResourceGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceGroupOperatorSpec. +func (in *ResourceGroupOperatorSpec) DeepCopy() *ResourceGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ResourceGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceGroupProperties_STATUS) DeepCopyInto(out *ResourceGroupProperties_STATUS) { *out = *in @@ -180,6 +225,11 @@ func (in *ResourceGroup_Spec) DeepCopyInto(out *ResourceGroup_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ResourceGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) diff --git a/v2/api/resources/v1api20200601/structure.txt b/v2/api/resources/v1api20200601/structure.txt index c76b9fce843..3973adef271 100644 --- a/v2/api/resources/v1api20200601/structure.txt +++ b/v2/api/resources/v1api20200601/structure.txt @@ -4,12 +4,15 @@ github.com/Azure/azure-service-operator/v2/api/resources/v1api20200601 APIVersion: Enum (1 value) └── "2020-06-01" ResourceGroup: Resource -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 90 │ │ └── Rule 1: MinLength: 1 │ ├── Location: *string │ ├── ManagedBy: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Tags: map[string]string └── Status: Object (8 properties) ├── Conditions: conditions.Condition[] diff --git a/v2/api/resources/v1api20200601/zz_generated.deepcopy.go b/v2/api/resources/v1api20200601/zz_generated.deepcopy.go index 91973220b0b..29ae18b98d2 100644 --- a/v2/api/resources/v1api20200601/zz_generated.deepcopy.go +++ b/v2/api/resources/v1api20200601/zz_generated.deepcopy.go @@ -11,6 +11,7 @@ package v1api20200601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -73,6 +74,43 @@ func (in *ResourceGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceGroupOperatorSpec) DeepCopyInto(out *ResourceGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceGroupOperatorSpec. +func (in *ResourceGroupOperatorSpec) DeepCopy() *ResourceGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ResourceGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceGroupProperties_STATUS) DeepCopyInto(out *ResourceGroupProperties_STATUS) { *out = *in @@ -237,6 +275,11 @@ func (in *ResourceGroup_Spec) DeepCopyInto(out *ResourceGroup_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ResourceGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Tags != nil { in, out := &in.Tags, &out.Tags *out = make(map[string]string, len(*in)) diff --git a/v2/api/search/v1api20220901/search_service_types_gen.go b/v2/api/search/v1api20220901/search_service_types_gen.go index cfa4c70f104..5c2b75d7822 100644 --- a/v2/api/search/v1api20220901/search_service_types_gen.go +++ b/v2/api/search/v1api20220901/search_service_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -93,6 +95,26 @@ func (service *SearchService) defaultAzureName() { // defaultImpl applies the code generated defaults to the SearchService resource func (service *SearchService) defaultImpl() { service.defaultAzureName() } +var _ configmaps.Exporter = &SearchService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *SearchService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SearchService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *SearchService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SearchService{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +233,7 @@ func (service *SearchService) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (service *SearchService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -232,7 +254,18 @@ func (service *SearchService) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return service.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *SearchService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -254,15 +287,15 @@ func (service *SearchService) validateSecretDestinations() (admission.Warnings, if service.Spec.OperatorSpec == nil { return nil, nil } - if service.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - service.Spec.OperatorSpec.Secrets.AdminPrimaryKey, - service.Spec.OperatorSpec.Secrets.AdminSecondaryKey, - service.Spec.OperatorSpec.Secrets.QueryKey, + var toValidate []*genruntime.SecretDestination + if service.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + service.Spec.OperatorSpec.Secrets.AdminPrimaryKey, + service.Spec.OperatorSpec.Secrets.AdminSecondaryKey, + service.Spec.OperatorSpec.Secrets.QueryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(service, toValidate, service.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2808,6 +2841,12 @@ func (connection *PrivateEndpointConnection_STATUS) AssignProperties_To_PrivateE // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SearchServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *SearchServiceOperatorSecrets `json:"secrets,omitempty"` } @@ -2815,6 +2854,42 @@ type SearchServiceOperatorSpec struct { // AssignProperties_From_SearchServiceOperatorSpec populates our SearchServiceOperatorSpec from the provided source SearchServiceOperatorSpec func (operator *SearchServiceOperatorSpec) AssignProperties_From_SearchServiceOperatorSpec(source *storage.SearchServiceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret SearchServiceOperatorSecrets @@ -2836,6 +2911,42 @@ func (operator *SearchServiceOperatorSpec) AssignProperties_To_SearchServiceOper // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.SearchServiceOperatorSecrets diff --git a/v2/api/search/v1api20220901/storage/search_service_types_gen.go b/v2/api/search/v1api20220901/storage/search_service_types_gen.go index a3aaed42d4e..34ca8393351 100644 --- a/v2/api/search/v1api20220901/storage/search_service_types_gen.go +++ b/v2/api/search/v1api20220901/storage/search_service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (service *SearchService) SetConditions(conditions conditions.Conditions) { service.Status.Conditions = conditions } +var _ configmaps.Exporter = &SearchService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *SearchService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SearchService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *SearchService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SearchService{} // AzureName returns the Azure name of the resource @@ -315,8 +338,10 @@ type PrivateEndpointConnection_STATUS struct { // Storage version of v1api20220901.SearchServiceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SearchServiceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *SearchServiceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *SearchServiceOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20220901.SharedPrivateLinkResource_STATUS diff --git a/v2/api/search/v1api20220901/storage/structure.txt b/v2/api/search/v1api20220901/storage/structure.txt index 179fb7ba094..2900d9b2cfa 100644 --- a/v2/api/search/v1api20220901/storage/structure.txt +++ b/v2/api/search/v1api20220901/storage/structure.txt @@ -26,8 +26,10 @@ SearchService: Resource │ │ │ ├── PropertyBag: genruntime.PropertyBag │ │ │ └── Value: *string │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── AdminPrimaryKey: *genruntime.SecretDestination │ │ ├── AdminSecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/search/v1api20220901/storage/zz_generated.deepcopy.go b/v2/api/search/v1api20220901/storage/zz_generated.deepcopy.go index 58ad89bedf6..02b23156247 100644 --- a/v2/api/search/v1api20220901/storage/zz_generated.deepcopy.go +++ b/v2/api/search/v1api20220901/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -492,6 +493,17 @@ func (in *SearchServiceOperatorSecrets) DeepCopy() *SearchServiceOperatorSecrets // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SearchServiceOperatorSpec) DeepCopyInto(out *SearchServiceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -499,6 +511,17 @@ func (in *SearchServiceOperatorSpec) DeepCopyInto(out *SearchServiceOperatorSpec (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SearchServiceOperatorSecrets) diff --git a/v2/api/search/v1api20220901/structure.txt b/v2/api/search/v1api20220901/structure.txt index 129b8b930f5..e27a57267db 100644 --- a/v2/api/search/v1api20220901/structure.txt +++ b/v2/api/search/v1api20220901/structure.txt @@ -29,7 +29,9 @@ SearchService: Resource │ ├── NetworkRuleSet: *Object (1 property) │ │ └── IpRules: Object (1 property)[] │ │ └── Value: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (3 properties) │ │ ├── AdminPrimaryKey: *genruntime.SecretDestination │ │ ├── AdminSecondaryKey: *genruntime.SecretDestination diff --git a/v2/api/search/v1api20220901/zz_generated.deepcopy.go b/v2/api/search/v1api20220901/zz_generated.deepcopy.go index 55a62e1fd77..e45e269cbb1 100644 --- a/v2/api/search/v1api20220901/zz_generated.deepcopy.go +++ b/v2/api/search/v1api20220901/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220901 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -394,6 +395,28 @@ func (in *SearchServiceOperatorSecrets) DeepCopy() *SearchServiceOperatorSecrets // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SearchServiceOperatorSpec) DeepCopyInto(out *SearchServiceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SearchServiceOperatorSecrets) diff --git a/v2/api/servicebus/v1api20210101preview/namespace_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespace_types_gen.go index 9464ea7f3fa..ad244bd43db 100644 --- a/v2/api/servicebus/v1api20210101preview/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespace_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (namespace *Namespace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Namespace resource func (namespace *Namespace) defaultImpl() { namespace.defaultAzureName() } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (namespace *Namespace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (namespace *Namespace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations} + return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations, namespace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (namespace *Namespace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return namespace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return namespace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (namespace *Namespace) validateConfigMapDestinations() (admission.Warnings, error) { + if namespace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(namespace, nil, namespace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,17 +289,17 @@ func (namespace *Namespace) validateSecretDestinations() (admission.Warnings, er if namespace.Spec.OperatorSpec == nil { return nil, nil } - if namespace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - namespace.Spec.OperatorSpec.Secrets.Endpoint, - namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.PrimaryKey, - namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if namespace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + namespace.Spec.OperatorSpec.Secrets.Endpoint, + namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.PrimaryKey, + namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(namespace, toValidate, namespace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -1916,6 +1949,12 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } @@ -1923,6 +1962,42 @@ type NamespaceOperatorSpec struct { // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSpec(source *storage.NamespaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -1944,6 +2019,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespaces_authorization_rule_types_gen.go index 0706e2b3577..29e64943200 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_authorization_rule_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (rule *NamespacesAuthorizationRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesAuthorizationRule resource func (rule *NamespacesAuthorizationRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (rule *NamespacesAuthorizationRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *NamespacesAuthorizationRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,9 +256,20 @@ func (rule *NamespacesAuthorizationRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesAuthorizationRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *NamespacesAuthorizationRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -256,16 +289,16 @@ func (rule *NamespacesAuthorizationRule) validateSecretDestinations() (admission if rule.Spec.OperatorSpec == nil { return nil, nil } - if rule.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - rule.Spec.OperatorSpec.Secrets.PrimaryKey, - rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - rule.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if rule.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + rule.Spec.OperatorSpec.Secrets.PrimaryKey, + rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + rule.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(rule, toValidate, rule.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -849,6 +882,12 @@ var namespaces_AuthorizationRule_Properties_Rights_STATUS_Values = map[string]Na // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } @@ -856,6 +895,42 @@ type NamespacesAuthorizationRuleOperatorSpec struct { // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec(source *storage.NamespacesAuthorizationRuleOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -877,6 +952,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen.go index 6bcb178c5fa..36509e5cdba 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (queue *NamespacesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesQueue resource func (queue *NamespacesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesQueue{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (queue *NamespacesQueue) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (queue *NamespacesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (queue *NamespacesQueue) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *NamespacesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (queue *NamespacesQueue) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *NamespacesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *NamespacesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesQueue) @@ -379,6 +424,10 @@ type NamespacesQueue_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -603,6 +652,8 @@ func (queue *NamespacesQueue_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -743,6 +794,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_From_NamespacesQueue_Spec(so // MaxSizeInMegabytes queue.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -835,6 +898,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_To_NamespacesQueue_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(queue.MaxSizeInMegabytes) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.NamespacesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_NamespacesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -1698,6 +1773,110 @@ func (details *MessageCountDetails_STATUS) AssignProperties_To_MessageCountDetai return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesQueueOperatorSpec populates our NamespacesQueueOperatorSpec from the provided source NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_From_NamespacesQueueOperatorSpec(source *storage.NamespacesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesQueueOperatorSpec populates the provided destination NamespacesQueueOperatorSpec from our NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_To_NamespacesQueueOperatorSpec(destination *storage.NamespacesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen_test.go index eadf36c19da..903f9cdf7a0 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_queue_types_gen_test.go @@ -272,6 +272,103 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesQueueOperatorSpec to NamespacesQueueOperatorSpec via AssignProperties_To_NamespacesQueueOperatorSpec & AssignProperties_From_NamespacesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesQueueOperatorSpec tests if a specific instance of NamespacesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210101ps.NamespacesQueueOperatorSpec + err := copied.AssignProperties_To_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesQueueOperatorSpec + err = actual.AssignProperties_From_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -507,6 +604,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -516,6 +616,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -537,3 +643,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen.go index f1d15140090..6034f0b2e2b 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (topic *NamespacesTopic) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopic resource func (topic *NamespacesTopic) defaultImpl() { topic.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopic{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (topic *NamespacesTopic) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (topic *NamespacesTopic) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference} + return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference, topic.validateSecretDestinations, topic.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (topic *NamespacesTopic) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return topic.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (topic *NamespacesTopic) validateConfigMapDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (topic *NamespacesTopic) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (topic *NamespacesTopic) validateSecretDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (topic *NamespacesTopic) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopic) @@ -361,6 +406,10 @@ type NamespacesTopic_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -515,6 +564,8 @@ func (topic *NamespacesTopic_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": topic.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -635,6 +686,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_From_NamespacesTopic_Spec(so // MaxSizeInMegabytes topic.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -707,6 +770,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_To_NamespacesTopic_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(topic.MaxSizeInMegabytes) + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_NamespacesTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion() @@ -1320,6 +1395,110 @@ func (topic *NamespacesTopic_STATUS) AssignProperties_To_NamespacesTopic_STATUS( return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicOperatorSpec populates our NamespacesTopicOperatorSpec from the provided source NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_From_NamespacesTopicOperatorSpec(source *storage.NamespacesTopicOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicOperatorSpec populates the provided destination NamespacesTopicOperatorSpec from our NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_To_NamespacesTopicOperatorSpec(destination *storage.NamespacesTopicOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen_test.go index 684c291eea3..08537d97f57 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topic_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicOperatorSpec to NamespacesTopicOperatorSpec via AssignProperties_To_NamespacesTopicOperatorSpec & AssignProperties_From_NamespacesTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicOperatorSpec tests if a specific instance of NamespacesTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210101ps.NamespacesTopicOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -395,6 +492,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -404,6 +504,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -420,3 +526,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen.go index f3c7f866e80..752622de59b 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (subscription *NamespacesTopicsSubscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscription resource func (subscription *NamespacesTopicsSubscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscription{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (subscription *NamespacesTopicsSubscription) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (subscription *NamespacesTopicsSubscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (subscription *NamespacesTopicsSubscription) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return subscription.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *NamespacesTopicsSubscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (subscription *NamespacesTopicsSubscription) validateResourceReferences() ( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (subscription *NamespacesTopicsSubscription) validateSecretDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (subscription *NamespacesTopicsSubscription) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscription) @@ -371,6 +416,10 @@ type NamespacesTopicsSubscription_Spec struct { // MaxDeliveryCount: Number of maximum deliveries. MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -559,6 +608,8 @@ func (subscription *NamespacesTopicsSubscription_Spec) PopulateFromARM(owner gen } } + // no assignment for property "OperatorSpec" + // Set property "Owner": subscription.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -679,6 +730,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_From_Nam // MaxDeliveryCount subscription.MaxDeliveryCount = genruntime.ClonePointerToInt(source.MaxDeliveryCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -752,6 +815,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_To_Names // MaxDeliveryCount destination.MaxDeliveryCount = genruntime.ClonePointerToInt(subscription.MaxDeliveryCount) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion() @@ -1367,6 +1442,110 @@ func (subscription *NamespacesTopicsSubscription_STATUS) AssignProperties_To_Nam return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec populates our NamespacesTopicsSubscriptionOperatorSpec from the provided source NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec populates the provided destination NamespacesTopicsSubscriptionOperatorSpec from our NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(destination *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesTopicsSubscription{}, &NamespacesTopicsSubscriptionList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen_test.go index 35f6f7e9664..889e7802eaf 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscription_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionOperatorSpec to NamespacesTopicsSubscriptionOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210101ps.NamespacesTopicsSubscriptionOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -397,6 +494,9 @@ func RunJSONSerializationTestForNamespacesTopicsSubscription_Spec(subject Namesp var namespacesTopicsSubscription_SpecGenerator gopter.Gen // NamespacesTopicsSubscription_SpecGenerator returns a generator of NamespacesTopicsSubscription_Spec instances for property testing. +// We first initialize namespacesTopicsSubscription_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopicsSubscription_SpecGenerator() gopter.Gen { if namespacesTopicsSubscription_SpecGenerator != nil { return namespacesTopicsSubscription_SpecGenerator @@ -406,6 +506,12 @@ func NamespacesTopicsSubscription_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) namespacesTopicsSubscription_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscription_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) + namespacesTopicsSubscription_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscription_Spec{}), generators) + return namespacesTopicsSubscription_SpecGenerator } @@ -424,3 +530,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m gens["MaxDeliveryCount"] = gen.PtrOf(gen.Int()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen.go index 186bb71fd7a..9dddfdf3b26 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscriptionsRule resource func (rule *NamespacesTopicsSubscriptionsRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscriptionsRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *NamespacesTopicsSubscriptionsRule) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (rule *NamespacesTopicsSubscriptionsRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *NamespacesTopicsSubscriptionsRule) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesTopicsSubscriptionsRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *NamespacesTopicsSubscriptionsRule) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *NamespacesTopicsSubscriptionsRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *NamespacesTopicsSubscriptionsRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscriptionsRule) @@ -345,6 +390,10 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // FilterType: Filter type that is evaluated against a BrokeredMessage. FilterType *FilterType `json:"filterType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -461,6 +510,8 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -574,6 +625,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_From_Namesp rule.FilterType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionsRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -638,6 +701,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_To_Namespac destination.FilterType = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1765,6 +1840,110 @@ var filterType_STATUS_Values = map[string]FilterType_STATUS{ "sqlfilter": FilterType_STATUS_SqlFilter, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec populates our NamespacesTopicsSubscriptionsRuleOperatorSpec from the provided source NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec populates the provided destination NamespacesTopicsSubscriptionsRuleOperatorSpec from our NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(destination *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { // +kubebuilder:validation:Maximum=20 diff --git a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen_test.go index 916bb85da8f..a2f925f9510 100644 --- a/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -601,6 +601,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionsRuleOperatorSpec to NamespacesTopicsSubscriptionsRuleOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210101ps.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -841,6 +938,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespace_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespace_types_gen.go index 883371f2876..6eb5de6fa64 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespace_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (namespace *Namespace) ConvertTo(hub conversion.Hub) error { return namespace.AssignProperties_To_Namespace(destination) } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -1395,8 +1418,10 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Storage version of v1api20210101preview.NamespaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec @@ -1404,6 +1429,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -1441,6 +1502,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_authorization_rule_types_gen.go index b74ee9b1eb9..1b630ca70b2 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_authorization_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *NamespacesAuthorizationRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_NamespacesAuthorizationRule(destination) } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -604,8 +627,10 @@ type augmentConversionForNamespacesAuthorizationRule_STATUS interface { // Storage version of v1api20210101preview.NamespacesAuthorizationRuleOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec @@ -613,6 +638,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_N // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -650,6 +711,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen.go index 9cf904aa53c..3e17a5dd202 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (queue *NamespacesQueue) ConvertTo(hub conversion.Hub) error { return queue.AssignProperties_To_NamespacesQueue(destination) } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesQueue{} // AzureName returns the Azure name of the resource @@ -237,19 +260,20 @@ type NamespacesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -382,6 +406,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_From_NamespacesQueue_Spec(so // MaxSizeInMegabytes queue.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // OriginalVersion queue.OriginalVersion = source.OriginalVersion @@ -506,6 +542,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_To_NamespacesQueue_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(queue.MaxSizeInMegabytes) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.NamespacesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_NamespacesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion @@ -1077,11 +1125,146 @@ func (details *MessageCountDetails_STATUS) AssignProperties_To_MessageCountDetai return nil } +// Storage version of v1api20210101preview.NamespacesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesQueueOperatorSpec populates our NamespacesQueueOperatorSpec from the provided source NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_From_NamespacesQueueOperatorSpec(source *storage.NamespacesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesQueueOperatorSpec populates the provided destination NamespacesQueueOperatorSpec from our NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_To_NamespacesQueueOperatorSpec(destination *storage.NamespacesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForMessageCountDetails_STATUS interface { AssignPropertiesFrom(src *storage.MessageCountDetails_STATUS) error AssignPropertiesTo(dst *storage.MessageCountDetails_STATUS) error } +type augmentConversionForNamespacesQueueOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesQueueOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesQueueOperatorSpec) error +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen_test.go index 4d980c05fa7..60aa9aaaeae 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_queue_types_gen_test.go @@ -271,6 +271,103 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesQueueOperatorSpec to NamespacesQueueOperatorSpec via AssignProperties_To_NamespacesQueueOperatorSpec & AssignProperties_From_NamespacesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesQueueOperatorSpec tests if a specific instance of NamespacesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesQueueOperatorSpec + err := copied.AssignProperties_To_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesQueueOperatorSpec + err = actual.AssignProperties_From_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -497,6 +594,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -506,6 +606,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -528,3 +634,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen.go index a450f4904bf..ba71bb94832 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (topic *NamespacesTopic) ConvertTo(hub conversion.Hub) error { return topic.AssignProperties_To_NamespacesTopic(destination) } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopic{} // AzureName returns the Azure name of the resource @@ -237,14 +260,15 @@ type NamespacesTopic_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -357,6 +381,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_From_NamespacesTopic_Spec(so // MaxSizeInMegabytes topic.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // OriginalVersion topic.OriginalVersion = source.OriginalVersion @@ -461,6 +497,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_To_NamespacesTopic_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(topic.MaxSizeInMegabytes) + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_NamespacesTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion @@ -896,6 +944,141 @@ type augmentConversionForNamespacesTopic_STATUS interface { AssignPropertiesTo(dst *storage.NamespacesTopic_STATUS) error } +// Storage version of v1api20210101preview.NamespacesTopicOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicOperatorSpec populates our NamespacesTopicOperatorSpec from the provided source NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_From_NamespacesTopicOperatorSpec(source *storage.NamespacesTopicOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicOperatorSpec populates the provided destination NamespacesTopicOperatorSpec from our NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_To_NamespacesTopicOperatorSpec(destination *storage.NamespacesTopicOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForNamespacesTopicOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicOperatorSpec) error +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen_test.go index 17829ce6f87..5336e078278 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topic_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicOperatorSpec to NamespacesTopicOperatorSpec via AssignProperties_To_NamespacesTopicOperatorSpec & AssignProperties_From_NamespacesTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicOperatorSpec tests if a specific instance of NamespacesTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,6 +482,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -394,6 +494,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -411,3 +517,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen.go index 548b0a6f3b8..28c7d7920fb 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (subscription *NamespacesTopicsSubscription) ConvertTo(hub conversion.Hub) return subscription.AssignProperties_To_NamespacesTopicsSubscription(destination) } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscription{} // AzureName returns the Azure name of the resource @@ -237,17 +260,18 @@ type NamespacesTopicsSubscription_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -375,6 +399,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_From_Nam // MaxDeliveryCount subscription.MaxDeliveryCount = genruntime.ClonePointerToInt(source.MaxDeliveryCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // OriginalVersion subscription.OriginalVersion = source.OriginalVersion @@ -493,6 +529,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_To_Names // MaxDeliveryCount destination.MaxDeliveryCount = genruntime.ClonePointerToInt(subscription.MaxDeliveryCount) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion @@ -937,6 +985,141 @@ type augmentConversionForNamespacesTopicsSubscription_STATUS interface { AssignPropertiesTo(dst *storage.NamespacesTopicsSubscription_STATUS) error } +// Storage version of v1api20210101preview.NamespacesTopicsSubscriptionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec populates our NamespacesTopicsSubscriptionOperatorSpec from the provided source NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec populates the provided destination NamespacesTopicsSubscriptionOperatorSpec from our NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(destination *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicsSubscriptionOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicsSubscriptionOperatorSpec) error +} + func init() { SchemeBuilder.Register(&NamespacesTopicsSubscription{}, &NamespacesTopicsSubscriptionList{}) } diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen_test.go index 53740bec663..6b0e4364ab2 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscription_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionOperatorSpec to NamespacesTopicsSubscriptionOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -387,6 +484,9 @@ func RunJSONSerializationTestForNamespacesTopicsSubscription_Spec(subject Namesp var namespacesTopicsSubscription_SpecGenerator gopter.Gen // NamespacesTopicsSubscription_SpecGenerator returns a generator of NamespacesTopicsSubscription_Spec instances for property testing. +// We first initialize namespacesTopicsSubscription_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopicsSubscription_SpecGenerator() gopter.Gen { if namespacesTopicsSubscription_SpecGenerator != nil { return namespacesTopicsSubscription_SpecGenerator @@ -396,6 +496,12 @@ func NamespacesTopicsSubscription_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) namespacesTopicsSubscription_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscription_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(generators) + namespacesTopicsSubscription_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscription_Spec{}), generators) + return namespacesTopicsSubscription_SpecGenerator } @@ -415,3 +521,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m gens["OriginalVersion"] = gen.AlphaString() gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen.go index 7f691a3896b..483551dc8fa 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) ConvertTo(hub conversion.Hub) err return rule.AssignProperties_To_NamespacesTopicsSubscriptionsRule(destination) } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscriptionsRule{} // AzureName returns the Azure name of the resource @@ -237,10 +260,11 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` - FilterType *string `json:"filterType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` + FilterType *string `json:"filterType,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -336,6 +360,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_From_Namesp // FilterType rule.FilterType = genruntime.ClonePointerToString(source.FilterType) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionsRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -414,6 +450,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_To_Namespac // FilterType destination.FilterType = genruntime.ClonePointerToString(rule.FilterType) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -1175,6 +1223,136 @@ func (filter *CorrelationFilter_STATUS) AssignProperties_To_CorrelationFilter_ST return nil } +// Storage version of v1api20210101preview.NamespacesTopicsSubscriptionsRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec populates our NamespacesTopicsSubscriptionsRuleOperatorSpec from the provided source NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec populates the provided destination NamespacesTopicsSubscriptionsRuleOperatorSpec from our NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(destination *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20210101preview.SqlFilter // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { @@ -1369,6 +1547,11 @@ type augmentConversionForCorrelationFilter_STATUS interface { AssignPropertiesTo(dst *storage.CorrelationFilter_STATUS) error } +type augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error +} + type augmentConversionForSqlFilter interface { AssignPropertiesFrom(src *storage.SqlFilter) error AssignPropertiesTo(dst *storage.SqlFilter) error diff --git a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go index 58099938aa5..0ae83cb6f18 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20210101preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -600,6 +600,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionsRuleOperatorSpec to NamespacesTopicsSubscriptionsRuleOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -841,6 +938,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20210101preview/storage/structure.txt b/v2/api/servicebus/v1api20210101preview/storage/structure.txt index 73e5bf9b4c3..aea5b08ab3d 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/structure.txt +++ b/v2/api/servicebus/v1api20210101preview/storage/structure.txt @@ -26,8 +26,10 @@ Namespace: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -101,8 +103,10 @@ NamespacesAuthorizationRule: Resource ├── Owner: servicebus/v1api20210101preview.Namespace ├── Spec: Object (6 properties) │ ├── AzureName: string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -130,7 +134,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: servicebus/v1api20210101preview.Namespace -├── Spec: Object (18 properties) +├── Spec: Object (19 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DeadLetteringOnMessageExpiration: *bool @@ -144,6 +148,10 @@ NamespacesQueue: Resource │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -192,7 +200,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: servicebus/v1api20210101preview.Namespace -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DefaultMessageTimeToLive: *string @@ -201,6 +209,10 @@ NamespacesTopic: Resource │ ├── EnableExpress: *bool │ ├── EnablePartitioning: *bool │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -244,7 +256,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: servicebus/v1api20210101preview.NamespacesTopic -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DeadLetteringOnFilterEvaluationExceptions: *bool @@ -256,6 +268,10 @@ NamespacesTopicsSubscription: Resource │ ├── ForwardTo: *string │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -299,7 +315,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: servicebus/v1api20210101preview.NamespacesTopicsSubscription -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── Action: *Object (4 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── PropertyBag: genruntime.PropertyBag @@ -319,6 +335,10 @@ NamespacesTopicsSubscriptionsRule: Resource │ │ ├── SessionId: *string │ │ └── To: *string │ ├── FilterType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -387,15 +407,19 @@ augmentConversionForNamespacesAuthorizationRuleOperatorSpec: Interface augmentConversionForNamespacesAuthorizationRule_STATUS: Interface augmentConversionForNamespacesAuthorizationRule_Spec: Interface augmentConversionForNamespacesQueue: Interface +augmentConversionForNamespacesQueueOperatorSpec: Interface augmentConversionForNamespacesQueue_STATUS: Interface augmentConversionForNamespacesQueue_Spec: Interface augmentConversionForNamespacesTopic: Interface +augmentConversionForNamespacesTopicOperatorSpec: Interface augmentConversionForNamespacesTopic_STATUS: Interface augmentConversionForNamespacesTopic_Spec: Interface augmentConversionForNamespacesTopicsSubscription: Interface +augmentConversionForNamespacesTopicsSubscriptionOperatorSpec: Interface augmentConversionForNamespacesTopicsSubscription_STATUS: Interface augmentConversionForNamespacesTopicsSubscription_Spec: Interface augmentConversionForNamespacesTopicsSubscriptionsRule: Interface +augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec: Interface augmentConversionForNamespacesTopicsSubscriptionsRule_STATUS: Interface augmentConversionForNamespacesTopicsSubscriptionsRule_Spec: Interface augmentConversionForPrivateEndpointConnection_STATUS: Interface diff --git a/v2/api/servicebus/v1api20210101preview/storage/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20210101preview/storage/zz_generated.deepcopy.go index 1030aed2d55..79b381c5f90 100644 --- a/v2/api/servicebus/v1api20210101preview/storage/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20210101preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -665,6 +666,17 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -672,6 +684,17 @@ func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -975,6 +998,17 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -982,6 +1016,17 @@ func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesA (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1149,6 +1194,50 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1366,6 +1455,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1459,6 +1553,50 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1626,6 +1764,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1719,6 +1862,50 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1906,6 +2093,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1994,6 +2186,50 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -2081,6 +2317,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/servicebus/v1api20210101preview/structure.txt b/v2/api/servicebus/v1api20210101preview/structure.txt index b078f71e361..288b8321b6f 100644 --- a/v2/api/servicebus/v1api20210101preview/structure.txt +++ b/v2/api/servicebus/v1api20210101preview/structure.txt @@ -26,7 +26,9 @@ Namespace: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -114,7 +116,9 @@ NamespacesAuthorizationRule: Resource │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ └── Rule 1: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -151,7 +155,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: Namespace -├── Spec: Object (16 properties) +├── Spec: Object (17 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -166,6 +170,9 @@ NamespacesQueue: Resource │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── RequiresSession: *bool @@ -226,7 +233,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: Namespace -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -236,6 +243,9 @@ NamespacesTopic: Resource │ ├── EnableExpress: *bool │ ├── EnablePartitioning: *bool │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── SupportOrdering: *bool @@ -291,7 +301,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: NamespacesTopic -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 @@ -305,6 +315,9 @@ NamespacesTopicsSubscription: Resource │ ├── ForwardTo: *string │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RequiresSession: *bool └── Status: Object (22 properties) @@ -360,7 +373,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: NamespacesTopicsSubscription -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Action: *Object (3 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── RequiresPreprocessing: *bool @@ -382,6 +395,9 @@ NamespacesTopicsSubscriptionsRule: Resource │ ├── FilterType: *Enum (2 values) │ │ ├── "CorrelationFilter" │ │ └── "SqlFilter" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── SqlFilter: *Object (3 properties) │ ├── CompatibilityLevel: Validated<*int> (2 rules) diff --git a/v2/api/servicebus/v1api20210101preview/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20210101preview/zz_generated.deepcopy.go index 0dbf37ae07e..63028a7782d 100644 --- a/v2/api/servicebus/v1api20210101preview/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20210101preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210101preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -572,6 +573,28 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -854,6 +877,28 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1007,6 +1052,43 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1217,6 +1299,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1303,6 +1390,43 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1463,6 +1587,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1549,6 +1678,43 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1729,6 +1895,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1810,6 +1981,43 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -1890,6 +2098,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(FilterType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/servicebus/v1api20211101/namespace_types_gen.go b/v2/api/servicebus/v1api20211101/namespace_types_gen.go index 017b7165c2c..49effd68224 100644 --- a/v2/api/servicebus/v1api20211101/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespace_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (namespace *Namespace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Namespace resource func (namespace *Namespace) defaultImpl() { namespace.defaultAzureName() } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Namespace{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (namespace *Namespace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (namespace *Namespace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations} + return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations, namespace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (namespace *Namespace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return namespace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return namespace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (namespace *Namespace) validateConfigMapDestinations() (admission.Warnings, error) { + if namespace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(namespace, nil, namespace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,17 +286,17 @@ func (namespace *Namespace) validateSecretDestinations() (admission.Warnings, er if namespace.Spec.OperatorSpec == nil { return nil, nil } - if namespace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - namespace.Spec.OperatorSpec.Secrets.Endpoint, - namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.PrimaryKey, - namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if namespace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + namespace.Spec.OperatorSpec.Secrets.Endpoint, + namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.PrimaryKey, + namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(namespace, toValidate, namespace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2152,6 +2185,12 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } @@ -2159,6 +2198,42 @@ type NamespaceOperatorSpec struct { // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSpec(source *storage.NamespaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -2180,6 +2255,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/servicebus/v1api20211101/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20211101/namespaces_authorization_rule_types_gen.go index ce2df9c1fba..07d9bfadffe 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespaces_authorization_rule_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (rule *NamespacesAuthorizationRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesAuthorizationRule resource func (rule *NamespacesAuthorizationRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesAuthorizationRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (rule *NamespacesAuthorizationRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *NamespacesAuthorizationRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,9 +253,20 @@ func (rule *NamespacesAuthorizationRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesAuthorizationRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *NamespacesAuthorizationRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -253,16 +286,16 @@ func (rule *NamespacesAuthorizationRule) validateSecretDestinations() (admission if rule.Spec.OperatorSpec == nil { return nil, nil } - if rule.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - rule.Spec.OperatorSpec.Secrets.PrimaryKey, - rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - rule.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if rule.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + rule.Spec.OperatorSpec.Secrets.PrimaryKey, + rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + rule.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(rule, toValidate, rule.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -883,6 +916,12 @@ var namespaces_AuthorizationRule_Properties_Rights_STATUS_Values = map[string]Na // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } @@ -890,6 +929,42 @@ type NamespacesAuthorizationRuleOperatorSpec struct { // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec(source *storage.NamespacesAuthorizationRuleOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -911,6 +986,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen.go index d26a99f6965..86c1179e1e9 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (queue *NamespacesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesQueue resource func (queue *NamespacesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesQueue{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (queue *NamespacesQueue) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (queue *NamespacesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (queue *NamespacesQueue) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *NamespacesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (queue *NamespacesQueue) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *NamespacesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *NamespacesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesQueue) @@ -380,6 +425,10 @@ type NamespacesQueue_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -618,6 +667,8 @@ func (queue *NamespacesQueue_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -761,6 +812,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_From_NamespacesQueue_Spec(so // MaxSizeInMegabytes queue.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -856,6 +919,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_To_NamespacesQueue_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(queue.MaxSizeInMegabytes) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.NamespacesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_NamespacesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -1836,6 +1911,110 @@ func (details *MessageCountDetails_STATUS) AssignProperties_To_MessageCountDetai return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesQueueOperatorSpec populates our NamespacesQueueOperatorSpec from the provided source NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_From_NamespacesQueueOperatorSpec(source *storage.NamespacesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesQueueOperatorSpec populates the provided destination NamespacesQueueOperatorSpec from our NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_To_NamespacesQueueOperatorSpec(destination *storage.NamespacesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen_test.go index cae97ae1394..65b2a70e024 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/namespaces_queue_types_gen_test.go @@ -271,6 +271,103 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesQueueOperatorSpec to NamespacesQueueOperatorSpec via AssignProperties_To_NamespacesQueueOperatorSpec & AssignProperties_From_NamespacesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesQueueOperatorSpec tests if a specific instance of NamespacesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesQueueOperatorSpec + err := copied.AssignProperties_To_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesQueueOperatorSpec + err = actual.AssignProperties_From_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -508,6 +605,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -517,6 +617,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -539,3 +645,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen.go index 4476d5f4ac7..ca6f0e8d8bd 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (topic *NamespacesTopic) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopic resource func (topic *NamespacesTopic) defaultImpl() { topic.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesTopic{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (topic *NamespacesTopic) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (topic *NamespacesTopic) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference} + return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference, topic.validateSecretDestinations, topic.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (topic *NamespacesTopic) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return topic.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (topic *NamespacesTopic) validateConfigMapDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (topic *NamespacesTopic) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (topic *NamespacesTopic) validateSecretDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (topic *NamespacesTopic) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopic) @@ -362,6 +407,10 @@ type NamespacesTopic_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -530,6 +579,8 @@ func (topic *NamespacesTopic_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": topic.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -653,6 +704,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_From_NamespacesTopic_Spec(so // MaxSizeInMegabytes topic.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -728,6 +791,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_To_NamespacesTopic_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(topic.MaxSizeInMegabytes) + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_NamespacesTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion() @@ -1438,6 +1513,110 @@ func (topic *NamespacesTopic_STATUS) AssignProperties_To_NamespacesTopic_STATUS( return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicOperatorSpec populates our NamespacesTopicOperatorSpec from the provided source NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_From_NamespacesTopicOperatorSpec(source *storage.NamespacesTopicOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicOperatorSpec populates the provided destination NamespacesTopicOperatorSpec from our NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_To_NamespacesTopicOperatorSpec(destination *storage.NamespacesTopicOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen_test.go index 80335bfb310..535cb9ff3b5 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topic_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicOperatorSpec to NamespacesTopicOperatorSpec via AssignProperties_To_NamespacesTopicOperatorSpec & AssignProperties_From_NamespacesTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicOperatorSpec tests if a specific instance of NamespacesTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -396,6 +493,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -405,6 +505,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -422,3 +528,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen.go index b68b11f3305..82251bac126 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (subscription *NamespacesTopicsSubscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscription resource func (subscription *NamespacesTopicsSubscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesTopicsSubscription{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (subscription *NamespacesTopicsSubscription) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (subscription *NamespacesTopicsSubscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (subscription *NamespacesTopicsSubscription) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return subscription.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *NamespacesTopicsSubscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (subscription *NamespacesTopicsSubscription) validateResourceReferences() ( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (subscription *NamespacesTopicsSubscription) validateSecretDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (subscription *NamespacesTopicsSubscription) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscription) @@ -374,6 +419,10 @@ type NamespacesTopicsSubscription_Spec struct { // MaxDeliveryCount: Number of maximum deliveries. MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -599,6 +648,8 @@ func (subscription *NamespacesTopicsSubscription_Spec) PopulateFromARM(owner gen } } + // no assignment for property "OperatorSpec" + // Set property "Owner": subscription.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -739,6 +790,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_From_Nam // MaxDeliveryCount subscription.MaxDeliveryCount = genruntime.ClonePointerToInt(source.MaxDeliveryCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -832,6 +895,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_To_Names // MaxDeliveryCount destination.MaxDeliveryCount = genruntime.ClonePointerToInt(subscription.MaxDeliveryCount) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion() @@ -1612,6 +1687,110 @@ func (subscription *NamespacesTopicsSubscription_STATUS) AssignProperties_To_Nam return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec populates our NamespacesTopicsSubscriptionOperatorSpec from the provided source NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec populates the provided destination NamespacesTopicsSubscriptionOperatorSpec from our NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(destination *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties specific to client affine subscriptions. type SBClientAffineProperties struct { // ClientId: Indicates the Client ID of the application that created the client-affine subscription. diff --git a/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen_test.go index f01e708c2d9..3a769828426 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topics_subscription_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionOperatorSpec to NamespacesTopicsSubscriptionOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -440,6 +537,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m // AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { gens["ClientAffineProperties"] = gen.PtrOf(SBClientAffinePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) } func Test_SBClientAffineProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen.go index 5176d41ffe1..514b7f934c2 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscriptionsRule resource func (rule *NamespacesTopicsSubscriptionsRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &NamespacesTopicsSubscriptionsRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *NamespacesTopicsSubscriptionsRule) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (rule *NamespacesTopicsSubscriptionsRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *NamespacesTopicsSubscriptionsRule) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesTopicsSubscriptionsRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *NamespacesTopicsSubscriptionsRule) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *NamespacesTopicsSubscriptionsRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *NamespacesTopicsSubscriptionsRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscriptionsRule) @@ -342,6 +387,10 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // FilterType: Filter type that is evaluated against a BrokeredMessage. FilterType *FilterType `json:"filterType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -458,6 +507,8 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -571,6 +622,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_From_Namesp rule.FilterType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionsRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -635,6 +698,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_To_Namespac destination.FilterType = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1892,6 +1967,110 @@ var filterType_STATUS_Values = map[string]FilterType_STATUS{ "sqlfilter": FilterType_STATUS_SqlFilter, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec populates our NamespacesTopicsSubscriptionsRuleOperatorSpec from the provided source NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec populates the provided destination NamespacesTopicsSubscriptionsRuleOperatorSpec from our NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(destination *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { // CompatibilityLevel: This property is reserved for future use. An integer value showing the compatibility level, diff --git a/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen_test.go index 6175e1b893e..bb4c9fcd57c 100644 --- a/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -600,6 +600,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionsRuleOperatorSpec to NamespacesTopicsSubscriptionsRuleOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -841,6 +938,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20211101/storage/namespace_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespace_types_gen.go index 5ed9c12a452..73b41f97ba5 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespace_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (namespace *Namespace) SetConditions(conditions conditions.Conditions) { namespace.Status.Conditions = conditions } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -273,8 +296,10 @@ type Identity_STATUS struct { // Storage version of v1api20211101.NamespaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211101.PrivateEndpointConnection_STATUS diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespaces_authorization_rule_types_gen.go index 0c5c7b794f2..b1be615e085 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_authorization_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *NamespacesAuthorizationRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -210,8 +233,10 @@ func (rule *NamespacesAuthorizationRule_STATUS) ConvertStatusTo(destination genr // Storage version of v1api20211101.NamespacesAuthorizationRuleOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211101.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen.go index 402b61bdf48..1886634a393 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (queue *NamespacesQueue) SetConditions(conditions conditions.Conditions) { queue.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesQueue{} // AzureName returns the Azure name of the resource @@ -144,20 +167,21 @@ type NamespacesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -253,6 +277,14 @@ type MessageCountDetails_STATUS struct { TransferMessageCount *int `json:"transferMessageCount,omitempty"` } +// Storage version of v1api20211101.NamespacesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen_test.go index ebe58559cf5..040f02b9e2e 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_queue_types_gen_test.go @@ -143,6 +143,61 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -287,6 +342,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -296,6 +354,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -319,3 +383,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen.go index 27964eb2281..8fc5d050d55 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (topic *NamespacesTopic) SetConditions(conditions conditions.Conditions) { topic.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopic{} // AzureName returns the Azure name of the resource @@ -144,15 +167,16 @@ type NamespacesTopic_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -232,6 +256,14 @@ func (topic *NamespacesTopic_STATUS) ConvertStatusTo(destination genruntime.Conv return destination.ConvertStatusFrom(topic) } +// Storage version of v1api20211101.NamespacesTopicOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen_test.go index 66a63760d6f..a9bde2ff7b6 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topic_types_gen_test.go @@ -78,6 +78,61 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -217,6 +272,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -226,6 +284,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -244,3 +308,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen.go index fe5e58c0b96..18f5724d114 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (subscription *NamespacesTopicsSubscription) SetConditions(conditions condi subscription.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscription{} // AzureName returns the Azure name of the resource @@ -144,19 +167,20 @@ type NamespacesTopicsSubscription_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClientAffineProperties *SBClientAffineProperties `json:"clientAffineProperties,omitempty"` - DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - IsClientAffine *bool `json:"isClientAffine,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClientAffineProperties *SBClientAffineProperties `json:"clientAffineProperties,omitempty"` + DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + IsClientAffine *bool `json:"isClientAffine,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -237,6 +261,14 @@ func (subscription *NamespacesTopicsSubscription_STATUS) ConvertStatusTo(destina return destination.ConvertStatusFrom(subscription) } +// Storage version of v1api20211101.NamespacesTopicsSubscriptionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.SBClientAffineProperties // Properties specific to client affine subscriptions. type SBClientAffineProperties struct { diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen_test.go index b25da5f4908..b93cfa1ccc6 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscription_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -262,6 +317,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m // AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { gens["ClientAffineProperties"] = gen.PtrOf(SBClientAffinePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) } func Test_SBClientAffineProperties_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen.go index 9cddf14b4c7..127795f01e6 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) SetConditions(conditions conditio rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscriptionsRule{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` - FilterType *string `json:"filterType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` + FilterType *string `json:"filterType,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -265,6 +289,14 @@ type CorrelationFilter_STATUS struct { To *string `json:"to,omitempty"` } +// Storage version of v1api20211101.NamespacesTopicsSubscriptionsRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.SqlFilter // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { diff --git a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen_test.go index a8494aa9dd5..ae7a756de2a 100644 --- a/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20211101/storage/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -346,6 +346,61 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -504,6 +559,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20211101/storage/structure.txt b/v2/api/servicebus/v1api20211101/storage/structure.txt index d99a6b8032d..4e58d174302 100644 --- a/v2/api/servicebus/v1api20211101/storage/structure.txt +++ b/v2/api/servicebus/v1api20211101/storage/structure.txt @@ -28,8 +28,10 @@ Namespace: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -105,8 +107,10 @@ NamespacesAuthorizationRule: Resource ├── Owner: servicebus/v1api20211101.Namespace ├── Spec: Object (6 properties) │ ├── AzureName: string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -135,7 +139,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: servicebus/v1api20211101.Namespace -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DeadLetteringOnMessageExpiration: *bool @@ -150,6 +154,10 @@ NamespacesQueue: Resource │ ├── MaxDeliveryCount: *int │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -200,7 +208,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: servicebus/v1api20211101.Namespace -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DefaultMessageTimeToLive: *string @@ -210,6 +218,10 @@ NamespacesTopic: Resource │ ├── EnablePartitioning: *bool │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -255,7 +267,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: servicebus/v1api20211101.NamespacesTopic -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── ClientAffineProperties: *Object (4 properties) @@ -273,6 +285,10 @@ NamespacesTopicsSubscription: Resource │ ├── IsClientAffine: *bool │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -323,7 +339,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: servicebus/v1api20211101.NamespacesTopicsSubscription -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── Action: *Object (4 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── PropertyBag: genruntime.PropertyBag @@ -343,6 +359,10 @@ NamespacesTopicsSubscriptionsRule: Resource │ │ ├── SessionId: *string │ │ └── To: *string │ ├── FilterType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/servicebus/v1api20211101/storage/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20211101/storage/zz_generated.deepcopy.go index ad3a6cc655f..80fa48cf228 100644 --- a/v2/api/servicebus/v1api20211101/storage/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20211101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -633,6 +634,17 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -640,6 +652,17 @@ func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -963,6 +986,17 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -970,6 +1004,17 @@ func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesA (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1142,6 +1187,50 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1374,6 +1463,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1467,6 +1561,50 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1649,6 +1787,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1742,6 +1885,50 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1954,6 +2141,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2042,6 +2234,50 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -2134,6 +2370,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/servicebus/v1api20211101/structure.txt b/v2/api/servicebus/v1api20211101/structure.txt index ed6ee6ae27e..a999b40df3b 100644 --- a/v2/api/servicebus/v1api20211101/structure.txt +++ b/v2/api/servicebus/v1api20211101/structure.txt @@ -28,7 +28,9 @@ Namespace: Resource │ │ └── UserAssignedIdentities: Object (1 property)[] │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -118,7 +120,9 @@ NamespacesAuthorizationRule: Resource │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ └── Rule 1: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -156,7 +160,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: Namespace -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -172,6 +176,9 @@ NamespacesQueue: Resource │ ├── MaxDeliveryCount: *int │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── RequiresSession: *bool @@ -234,7 +241,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: Namespace -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -245,6 +252,9 @@ NamespacesTopic: Resource │ ├── EnablePartitioning: *bool │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── SupportOrdering: *bool @@ -302,7 +312,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: NamespacesTopic -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 @@ -321,6 +331,9 @@ NamespacesTopicsSubscription: Resource │ ├── IsClientAffine: *bool │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RequiresSession: *bool └── Status: Object (25 properties) @@ -382,7 +395,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: NamespacesTopicsSubscription -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Action: *Object (3 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── RequiresPreprocessing: *bool @@ -404,6 +417,9 @@ NamespacesTopicsSubscriptionsRule: Resource │ ├── FilterType: *Enum (2 values) │ │ ├── "CorrelationFilter" │ │ └── "SqlFilter" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── SqlFilter: *Object (3 properties) │ ├── CompatibilityLevel: *int diff --git a/v2/api/servicebus/v1api20211101/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20211101/zz_generated.deepcopy.go index 24905f02bf4..ff855df7179 100644 --- a/v2/api/servicebus/v1api20211101/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20211101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20211101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -547,6 +548,28 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -849,6 +872,28 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1007,6 +1052,43 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1232,6 +1314,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1318,6 +1405,43 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1493,6 +1617,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1579,6 +1708,43 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1784,6 +1950,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1865,6 +2036,43 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -1950,6 +2158,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(FilterType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/servicebus/v1api20221001preview/namespace_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespace_types_gen.go index 0c781f5a86d..83d1b35fa8e 100644 --- a/v2/api/servicebus/v1api20221001preview/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespace_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (namespace *Namespace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Namespace resource func (namespace *Namespace) defaultImpl() { namespace.defaultAzureName() } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (namespace *Namespace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (namespace *Namespace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations} + return []func() (admission.Warnings, error){namespace.validateResourceReferences, namespace.validateOwnerReference, namespace.validateSecretDestinations, namespace.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,7 +256,18 @@ func (namespace *Namespace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return namespace.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return namespace.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (namespace *Namespace) validateConfigMapDestinations() (admission.Warnings, error) { + if namespace.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(namespace, nil, namespace.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -256,17 +289,17 @@ func (namespace *Namespace) validateSecretDestinations() (admission.Warnings, er if namespace.Spec.OperatorSpec == nil { return nil, nil } - if namespace.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - namespace.Spec.OperatorSpec.Secrets.Endpoint, - namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.PrimaryKey, - namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if namespace.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + namespace.Spec.OperatorSpec.Secrets.Endpoint, + namespace.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.PrimaryKey, + namespace.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + namespace.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(namespace, toValidate, namespace.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -2200,6 +2233,12 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } @@ -2207,6 +2246,42 @@ type NamespaceOperatorSpec struct { // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSpec(source *storage.NamespaceOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -2228,6 +2303,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespaces_authorization_rule_types_gen.go index 83d553d64d1..791b5d5a49e 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_authorization_rule_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,6 +108,26 @@ func (rule *NamespacesAuthorizationRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesAuthorizationRule resource func (rule *NamespacesAuthorizationRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -213,7 +235,7 @@ func (rule *NamespacesAuthorizationRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *NamespacesAuthorizationRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -234,9 +256,20 @@ func (rule *NamespacesAuthorizationRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesAuthorizationRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *NamespacesAuthorizationRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -256,16 +289,16 @@ func (rule *NamespacesAuthorizationRule) validateSecretDestinations() (admission if rule.Spec.OperatorSpec == nil { return nil, nil } - if rule.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - rule.Spec.OperatorSpec.Secrets.PrimaryKey, - rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - rule.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if rule.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + rule.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + rule.Spec.OperatorSpec.Secrets.PrimaryKey, + rule.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + rule.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(rule, toValidate, rule.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -865,6 +898,12 @@ var namespaces_AuthorizationRule_Properties_Rights_STATUS_Values = map[string]Na // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } @@ -872,6 +911,42 @@ type NamespacesAuthorizationRuleOperatorSpec struct { // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec(source *storage.NamespacesAuthorizationRuleOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -893,6 +968,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen.go index 46961410164..1f2fd36a4d0 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (queue *NamespacesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesQueue resource func (queue *NamespacesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesQueue{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (queue *NamespacesQueue) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (queue *NamespacesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (queue *NamespacesQueue) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *NamespacesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (queue *NamespacesQueue) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *NamespacesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *NamespacesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesQueue) @@ -383,6 +428,10 @@ type NamespacesQueue_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -621,6 +670,8 @@ func (queue *NamespacesQueue_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -764,6 +815,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_From_NamespacesQueue_Spec(so // MaxSizeInMegabytes queue.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -859,6 +922,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_To_NamespacesQueue_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(queue.MaxSizeInMegabytes) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.NamespacesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_NamespacesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -1757,6 +1832,110 @@ func (details *MessageCountDetails_STATUS) AssignProperties_To_MessageCountDetai return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesQueueOperatorSpec populates our NamespacesQueueOperatorSpec from the provided source NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_From_NamespacesQueueOperatorSpec(source *storage.NamespacesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesQueueOperatorSpec populates the provided destination NamespacesQueueOperatorSpec from our NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_To_NamespacesQueueOperatorSpec(destination *storage.NamespacesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen_test.go index bd80c70974d..60d7c13e65a 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_queue_types_gen_test.go @@ -272,6 +272,103 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesQueueOperatorSpec to NamespacesQueueOperatorSpec via AssignProperties_To_NamespacesQueueOperatorSpec & AssignProperties_From_NamespacesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesQueueOperatorSpec tests if a specific instance of NamespacesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20221001ps.NamespacesQueueOperatorSpec + err := copied.AssignProperties_To_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesQueueOperatorSpec + err = actual.AssignProperties_From_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -509,6 +606,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -518,6 +618,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -540,3 +646,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen.go index fc10db42b5d..d91bbfadb2f 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (topic *NamespacesTopic) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopic resource func (topic *NamespacesTopic) defaultImpl() { topic.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopic{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (topic *NamespacesTopic) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (topic *NamespacesTopic) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference} + return []func() (admission.Warnings, error){topic.validateResourceReferences, topic.validateOwnerReference, topic.validateSecretDestinations, topic.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (topic *NamespacesTopic) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return topic.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return topic.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (topic *NamespacesTopic) validateConfigMapDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (topic *NamespacesTopic) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (topic *NamespacesTopic) validateSecretDestinations() (admission.Warnings, error) { + if topic.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(topic, nil, topic.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (topic *NamespacesTopic) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopic) @@ -365,6 +410,10 @@ type NamespacesTopic_Spec struct { // Default is 1024. MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -533,6 +582,8 @@ func (topic *NamespacesTopic_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": topic.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -656,6 +707,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_From_NamespacesTopic_Spec(so // MaxSizeInMegabytes topic.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -731,6 +794,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_To_NamespacesTopic_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(topic.MaxSizeInMegabytes) + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_NamespacesTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion() @@ -1379,6 +1454,110 @@ func (topic *NamespacesTopic_STATUS) AssignProperties_To_NamespacesTopic_STATUS( return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicOperatorSpec populates our NamespacesTopicOperatorSpec from the provided source NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_From_NamespacesTopicOperatorSpec(source *storage.NamespacesTopicOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicOperatorSpec populates the provided destination NamespacesTopicOperatorSpec from our NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_To_NamespacesTopicOperatorSpec(destination *storage.NamespacesTopicOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen_test.go index 60a84bd3b3c..38981d838b4 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topic_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicOperatorSpec to NamespacesTopicOperatorSpec via AssignProperties_To_NamespacesTopicOperatorSpec & AssignProperties_From_NamespacesTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicOperatorSpec tests if a specific instance of NamespacesTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20221001ps.NamespacesTopicOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -397,6 +494,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -406,6 +506,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -423,3 +529,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen.go index 87c49c87e27..f2755c99a03 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (subscription *NamespacesTopicsSubscription) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscription resource func (subscription *NamespacesTopicsSubscription) defaultImpl() { subscription.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscription{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (subscription *NamespacesTopicsSubscription) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (subscription *NamespacesTopicsSubscription) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference} + return []func() (admission.Warnings, error){subscription.validateResourceReferences, subscription.validateOwnerReference, subscription.validateSecretDestinations, subscription.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (subscription *NamespacesTopicsSubscription) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return subscription.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return subscription.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (subscription *NamespacesTopicsSubscription) validateConfigMapDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (subscription *NamespacesTopicsSubscription) validateResourceReferences() ( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (subscription *NamespacesTopicsSubscription) validateSecretDestinations() (admission.Warnings, error) { + if subscription.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(subscription, nil, subscription.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (subscription *NamespacesTopicsSubscription) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscription) @@ -377,6 +422,10 @@ type NamespacesTopicsSubscription_Spec struct { // MaxDeliveryCount: Number of maximum deliveries. MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -602,6 +651,8 @@ func (subscription *NamespacesTopicsSubscription_Spec) PopulateFromARM(owner gen } } + // no assignment for property "OperatorSpec" + // Set property "Owner": subscription.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -742,6 +793,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_From_Nam // MaxDeliveryCount subscription.MaxDeliveryCount = genruntime.ClonePointerToInt(source.MaxDeliveryCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -835,6 +898,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_To_Names // MaxDeliveryCount destination.MaxDeliveryCount = genruntime.ClonePointerToInt(subscription.MaxDeliveryCount) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion() @@ -1535,6 +1610,110 @@ func (subscription *NamespacesTopicsSubscription_STATUS) AssignProperties_To_Nam return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec populates our NamespacesTopicsSubscriptionOperatorSpec from the provided source NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec populates the provided destination NamespacesTopicsSubscriptionOperatorSpec from our NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(destination *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties specific to client affine subscriptions. type SBClientAffineProperties struct { // ClientId: Indicates the Client ID of the application that created the client-affine subscription. diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen_test.go index 5081f565d67..bc0fe8a8250 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscription_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionOperatorSpec to NamespacesTopicsSubscriptionOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20221001ps.NamespacesTopicsSubscriptionOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -441,6 +538,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m // AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { gens["ClientAffineProperties"] = gen.PtrOf(SBClientAffinePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) } func Test_SBClientAffineProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen.go index f7cb944c5e5..43d45ddf6e7 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the NamespacesTopicsSubscriptionsRule resource func (rule *NamespacesTopicsSubscriptionsRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscriptionsRule{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (rule *NamespacesTopicsSubscriptionsRule) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (rule *NamespacesTopicsSubscriptionsRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (rule *NamespacesTopicsSubscriptionsRule) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *NamespacesTopicsSubscriptionsRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (rule *NamespacesTopicsSubscriptionsRule) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *NamespacesTopicsSubscriptionsRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *NamespacesTopicsSubscriptionsRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*NamespacesTopicsSubscriptionsRule) @@ -345,6 +390,10 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // FilterType: Filter type that is evaluated against a BrokeredMessage. FilterType *FilterType `json:"filterType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -461,6 +510,8 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -574,6 +625,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_From_Namesp rule.FilterType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionsRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -638,6 +701,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_To_Namespac destination.FilterType = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -1781,6 +1856,110 @@ var filterType_STATUS_Values = map[string]FilterType_STATUS{ "sqlfilter": FilterType_STATUS_SqlFilter, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec populates our NamespacesTopicsSubscriptionsRuleOperatorSpec from the provided source NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec populates the provided destination NamespacesTopicsSubscriptionsRuleOperatorSpec from our NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(destination *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { // CompatibilityLevel: This property is reserved for future use. An integer value showing the compatibility level, diff --git a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen_test.go index a8599f9baf7..991603c16ce 100644 --- a/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -601,6 +601,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionsRuleOperatorSpec to NamespacesTopicsSubscriptionsRuleOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20221001ps.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -842,6 +939,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespace_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespace_types_gen.go index fdeb086337c..d3e0b01ad92 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespace_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespace_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (namespace *Namespace) ConvertTo(hub conversion.Hub) error { return namespace.AssignProperties_To_Namespace(destination) } +var _ configmaps.Exporter = &Namespace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (namespace *Namespace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Namespace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (namespace *Namespace) SecretDestinationExpressions() []*core.DestinationExpression { + if namespace.Spec.OperatorSpec == nil { + return nil + } + return namespace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Namespace{} // AzureName returns the Azure name of the resource @@ -1490,8 +1513,10 @@ func (identity *Identity_STATUS) AssignProperties_To_Identity_STATUS(destination // Storage version of v1api20221001preview.NamespaceOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespaceOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespaceOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_NamespaceOperatorSpec populates our NamespaceOperatorSpec from the provided source NamespaceOperatorSpec @@ -1499,6 +1524,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_From_NamespaceOperatorSp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespaceOperatorSecrets @@ -1536,6 +1597,42 @@ func (operator *NamespaceOperatorSpec) AssignProperties_To_NamespaceOperatorSpec // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespaceOperatorSecrets diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_authorization_rule_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_authorization_rule_types_gen.go index c9010cad063..f9a9ca1a0df 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_authorization_rule_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_authorization_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *NamespacesAuthorizationRule) ConvertTo(hub conversion.Hub) error { return rule.AssignProperties_To_NamespacesAuthorizationRule(destination) } +var _ configmaps.Exporter = &NamespacesAuthorizationRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesAuthorizationRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesAuthorizationRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesAuthorizationRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesAuthorizationRule{} // AzureName returns the Azure name of the resource @@ -591,8 +614,10 @@ type augmentConversionForNamespacesAuthorizationRule_STATUS interface { // Storage version of v1api20221001preview.NamespacesAuthorizationRuleOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type NamespacesAuthorizationRuleOperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *NamespacesAuthorizationRuleOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_NamespacesAuthorizationRuleOperatorSpec populates our NamespacesAuthorizationRuleOperatorSpec from the provided source NamespacesAuthorizationRuleOperatorSpec @@ -600,6 +625,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_From_N // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret NamespacesAuthorizationRuleOperatorSecrets @@ -637,6 +698,42 @@ func (operator *NamespacesAuthorizationRuleOperatorSpec) AssignProperties_To_Nam // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.NamespacesAuthorizationRuleOperatorSecrets diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen.go index 43255d0031e..f97d6757ed6 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (queue *NamespacesQueue) ConvertTo(hub conversion.Hub) error { return queue.AssignProperties_To_NamespacesQueue(destination) } +var _ configmaps.Exporter = &NamespacesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *NamespacesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *NamespacesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesQueue{} // AzureName returns the Azure name of the resource @@ -237,20 +260,21 @@ type NamespacesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -379,6 +403,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_From_NamespacesQueue_Spec(so // MaxSizeInMegabytes queue.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // OriginalVersion queue.OriginalVersion = source.OriginalVersion @@ -493,6 +529,18 @@ func (queue *NamespacesQueue_Spec) AssignProperties_To_NamespacesQueue_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(queue.MaxSizeInMegabytes) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.NamespacesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_NamespacesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion @@ -1038,11 +1086,146 @@ func (details *MessageCountDetails_STATUS) AssignProperties_To_MessageCountDetai return nil } +// Storage version of v1api20221001preview.NamespacesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesQueueOperatorSpec populates our NamespacesQueueOperatorSpec from the provided source NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_From_NamespacesQueueOperatorSpec(source *storage.NamespacesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesQueueOperatorSpec populates the provided destination NamespacesQueueOperatorSpec from our NamespacesQueueOperatorSpec +func (operator *NamespacesQueueOperatorSpec) AssignProperties_To_NamespacesQueueOperatorSpec(destination *storage.NamespacesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForMessageCountDetails_STATUS interface { AssignPropertiesFrom(src *storage.MessageCountDetails_STATUS) error AssignPropertiesTo(dst *storage.MessageCountDetails_STATUS) error } +type augmentConversionForNamespacesQueueOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesQueueOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesQueueOperatorSpec) error +} + func init() { SchemeBuilder.Register(&NamespacesQueue{}, &NamespacesQueueList{}) } diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen_test.go index 7f0d947b9f0..e39fd09ca1b 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_queue_types_gen_test.go @@ -271,6 +271,103 @@ func AddRelatedPropertyGeneratorsForNamespacesQueue(gens map[string]gopter.Gen) gens["Status"] = NamespacesQueue_STATUSGenerator() } +func Test_NamespacesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesQueueOperatorSpec to NamespacesQueueOperatorSpec via AssignProperties_To_NamespacesQueueOperatorSpec & AssignProperties_From_NamespacesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesQueueOperatorSpec tests if a specific instance of NamespacesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesQueueOperatorSpec + err := copied.AssignProperties_To_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesQueueOperatorSpec + err = actual.AssignProperties_From_NamespacesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesQueueOperatorSpec, NamespacesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesQueueOperatorSpec runs a test to see if a specific instance of NamespacesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesQueueOperatorSpec(subject NamespacesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesQueueOperatorSpec instances for property testing - lazily instantiated by +// NamespacesQueueOperatorSpecGenerator() +var namespacesQueueOperatorSpecGenerator gopter.Gen + +// NamespacesQueueOperatorSpecGenerator returns a generator of NamespacesQueueOperatorSpec instances for property testing. +func NamespacesQueueOperatorSpecGenerator() gopter.Gen { + if namespacesQueueOperatorSpecGenerator != nil { + return namespacesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueueOperatorSpec{}), generators) + + return namespacesQueueOperatorSpecGenerator +} + func Test_NamespacesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -499,6 +596,9 @@ func RunJSONSerializationTestForNamespacesQueue_Spec(subject NamespacesQueue_Spe var namespacesQueue_SpecGenerator gopter.Gen // NamespacesQueue_SpecGenerator returns a generator of NamespacesQueue_Spec instances for property testing. +// We first initialize namespacesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesQueue_SpecGenerator() gopter.Gen { if namespacesQueue_SpecGenerator != nil { return namespacesQueue_SpecGenerator @@ -508,6 +608,12 @@ func NamespacesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(generators) + namespacesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesQueue_Spec{}), generators) + return namespacesQueue_SpecGenerator } @@ -531,3 +637,8 @@ func AddIndependentPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["RequiresSession"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen.go index 8da3c03423c..80d15ea6652 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (topic *NamespacesTopic) ConvertTo(hub conversion.Hub) error { return topic.AssignProperties_To_NamespacesTopic(destination) } +var _ configmaps.Exporter = &NamespacesTopic{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (topic *NamespacesTopic) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopic{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (topic *NamespacesTopic) SecretDestinationExpressions() []*core.DestinationExpression { + if topic.Spec.OperatorSpec == nil { + return nil + } + return topic.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopic{} // AzureName returns the Azure name of the resource @@ -237,15 +260,16 @@ type NamespacesTopic_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - EnableExpress *bool `json:"enableExpress,omitempty"` - EnablePartitioning *bool `json:"enablePartitioning,omitempty"` - MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` - MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + EnableExpress *bool `json:"enableExpress,omitempty"` + EnablePartitioning *bool `json:"enablePartitioning,omitempty"` + MaxMessageSizeInKilobytes *int `json:"maxMessageSizeInKilobytes,omitempty"` + MaxSizeInMegabytes *int `json:"maxSizeInMegabytes,omitempty"` + OperatorSpec *NamespacesTopicOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -354,6 +378,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_From_NamespacesTopic_Spec(so // MaxSizeInMegabytes topic.MaxSizeInMegabytes = genruntime.ClonePointerToInt(source.MaxSizeInMegabytes) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + topic.OperatorSpec = &operatorSpec + } else { + topic.OperatorSpec = nil + } + // OriginalVersion topic.OriginalVersion = source.OriginalVersion @@ -448,6 +484,18 @@ func (topic *NamespacesTopic_Spec) AssignProperties_To_NamespacesTopic_Spec(dest // MaxSizeInMegabytes destination.MaxSizeInMegabytes = genruntime.ClonePointerToInt(topic.MaxSizeInMegabytes) + // OperatorSpec + if topic.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicOperatorSpec + err := topic.OperatorSpec.AssignProperties_To_NamespacesTopicOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = topic.OriginalVersion @@ -857,6 +905,141 @@ type augmentConversionForNamespacesTopic_STATUS interface { AssignPropertiesTo(dst *storage.NamespacesTopic_STATUS) error } +// Storage version of v1api20221001preview.NamespacesTopicOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicOperatorSpec populates our NamespacesTopicOperatorSpec from the provided source NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_From_NamespacesTopicOperatorSpec(source *storage.NamespacesTopicOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicOperatorSpec populates the provided destination NamespacesTopicOperatorSpec from our NamespacesTopicOperatorSpec +func (operator *NamespacesTopicOperatorSpec) AssignProperties_To_NamespacesTopicOperatorSpec(destination *storage.NamespacesTopicOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForNamespacesTopicOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicOperatorSpec) error +} + func init() { SchemeBuilder.Register(&NamespacesTopic{}, &NamespacesTopicList{}) } diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen_test.go index faae0924e7c..67673a31209 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topic_types_gen_test.go @@ -164,6 +164,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopic(gens map[string]gopter.Gen) gens["Status"] = NamespacesTopic_STATUSGenerator() } +func Test_NamespacesTopicOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicOperatorSpec to NamespacesTopicOperatorSpec via AssignProperties_To_NamespacesTopicOperatorSpec & AssignProperties_From_NamespacesTopicOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicOperatorSpec tests if a specific instance of NamespacesTopicOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicOperatorSpec, NamespacesTopicOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicOperatorSpec runs a test to see if a specific instance of NamespacesTopicOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicOperatorSpec(subject NamespacesTopicOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicOperatorSpecGenerator() +var namespacesTopicOperatorSpecGenerator gopter.Gen + +// NamespacesTopicOperatorSpecGenerator returns a generator of NamespacesTopicOperatorSpec instances for property testing. +func NamespacesTopicOperatorSpecGenerator() gopter.Gen { + if namespacesTopicOperatorSpecGenerator != nil { + return namespacesTopicOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicOperatorSpec{}), generators) + + return namespacesTopicOperatorSpecGenerator +} + func Test_NamespacesTopic_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -387,6 +484,9 @@ func RunJSONSerializationTestForNamespacesTopic_Spec(subject NamespacesTopic_Spe var namespacesTopic_SpecGenerator gopter.Gen // NamespacesTopic_SpecGenerator returns a generator of NamespacesTopic_Spec instances for property testing. +// We first initialize namespacesTopic_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func NamespacesTopic_SpecGenerator() gopter.Gen { if namespacesTopic_SpecGenerator != nil { return namespacesTopic_SpecGenerator @@ -396,6 +496,12 @@ func NamespacesTopic_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(generators) + AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(generators) + namespacesTopic_SpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopic_Spec{}), generators) + return namespacesTopic_SpecGenerator } @@ -414,3 +520,8 @@ func AddIndependentPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gop gens["RequiresDuplicateDetection"] = gen.PtrOf(gen.Bool()) gens["SupportOrdering"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForNamespacesTopic_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForNamespacesTopic_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicOperatorSpecGenerator()) +} diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen.go index 133c52d294a..c6af4f75566 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (subscription *NamespacesTopicsSubscription) ConvertTo(hub conversion.Hub) return subscription.AssignProperties_To_NamespacesTopicsSubscription(destination) } +var _ configmaps.Exporter = &NamespacesTopicsSubscription{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (subscription *NamespacesTopicsSubscription) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscription{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (subscription *NamespacesTopicsSubscription) SecretDestinationExpressions() []*core.DestinationExpression { + if subscription.Spec.OperatorSpec == nil { + return nil + } + return subscription.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscription{} // AzureName returns the Azure name of the resource @@ -237,19 +260,20 @@ type NamespacesTopicsSubscription_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - ClientAffineProperties *SBClientAffineProperties `json:"clientAffineProperties,omitempty"` - DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` - DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` - DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` - DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` - EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` - ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` - ForwardTo *string `json:"forwardTo,omitempty"` - IsClientAffine *bool `json:"isClientAffine,omitempty"` - LockDuration *string `json:"lockDuration,omitempty"` - MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + ClientAffineProperties *SBClientAffineProperties `json:"clientAffineProperties,omitempty"` + DeadLetteringOnFilterEvaluationExceptions *bool `json:"deadLetteringOnFilterEvaluationExceptions,omitempty"` + DeadLetteringOnMessageExpiration *bool `json:"deadLetteringOnMessageExpiration,omitempty"` + DefaultMessageTimeToLive *string `json:"defaultMessageTimeToLive,omitempty"` + DuplicateDetectionHistoryTimeWindow *string `json:"duplicateDetectionHistoryTimeWindow,omitempty"` + EnableBatchedOperations *bool `json:"enableBatchedOperations,omitempty"` + ForwardDeadLetteredMessagesTo *string `json:"forwardDeadLetteredMessagesTo,omitempty"` + ForwardTo *string `json:"forwardTo,omitempty"` + IsClientAffine *bool `json:"isClientAffine,omitempty"` + LockDuration *string `json:"lockDuration,omitempty"` + MaxDeliveryCount *int `json:"maxDeliveryCount,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -383,6 +407,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_From_Nam // MaxDeliveryCount subscription.MaxDeliveryCount = genruntime.ClonePointerToInt(source.MaxDeliveryCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + subscription.OperatorSpec = &operatorSpec + } else { + subscription.OperatorSpec = nil + } + // OriginalVersion subscription.OriginalVersion = source.OriginalVersion @@ -495,6 +531,18 @@ func (subscription *NamespacesTopicsSubscription_Spec) AssignProperties_To_Names // MaxDeliveryCount destination.MaxDeliveryCount = genruntime.ClonePointerToInt(subscription.MaxDeliveryCount) + // OperatorSpec + if subscription.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionOperatorSpec + err := subscription.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = subscription.OriginalVersion @@ -928,6 +976,136 @@ type augmentConversionForNamespacesTopicsSubscription_STATUS interface { AssignPropertiesTo(dst *storage.NamespacesTopicsSubscription_STATUS) error } +// Storage version of v1api20221001preview.NamespacesTopicsSubscriptionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec populates our NamespacesTopicsSubscriptionOperatorSpec from the provided source NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(source *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec populates the provided destination NamespacesTopicsSubscriptionOperatorSpec from our NamespacesTopicsSubscriptionOperatorSpec +func (operator *NamespacesTopicsSubscriptionOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(destination *storage.NamespacesTopicsSubscriptionOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20221001preview.SBClientAffineProperties // Properties specific to client affine subscriptions. type SBClientAffineProperties struct { @@ -1122,6 +1300,11 @@ func (properties *SBClientAffineProperties_STATUS) AssignProperties_To_SBClientA return nil } +type augmentConversionForNamespacesTopicsSubscriptionOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicsSubscriptionOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicsSubscriptionOperatorSpec) error +} + type augmentConversionForSBClientAffineProperties interface { AssignPropertiesFrom(src *storage.SBClientAffineProperties) error AssignPropertiesTo(dst *storage.SBClientAffineProperties) error diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen_test.go index 8cae66518fc..c2c28cf7b4a 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscription_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription(gens map[string gens["Status"] = NamespacesTopicsSubscription_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionOperatorSpec to NamespacesTopicsSubscriptionOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec, NamespacesTopicsSubscriptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionOperatorSpec(subject NamespacesTopicsSubscriptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionOperatorSpecGenerator() +var namespacesTopicsSubscriptionOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscription_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -432,6 +529,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens m // AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscription_Spec(gens map[string]gopter.Gen) { gens["ClientAffineProperties"] = gen.PtrOf(SBClientAffinePropertiesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionOperatorSpecGenerator()) } func Test_SBClientAffineProperties_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen.go index cb49ae36cbe..4df6be51cf9 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/servicebus/v1api20211101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (rule *NamespacesTopicsSubscriptionsRule) ConvertTo(hub conversion.Hub) err return rule.AssignProperties_To_NamespacesTopicsSubscriptionsRule(destination) } +var _ configmaps.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &NamespacesTopicsSubscriptionsRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *NamespacesTopicsSubscriptionsRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &NamespacesTopicsSubscriptionsRule{} // AzureName returns the Azure name of the resource @@ -237,10 +260,11 @@ type NamespacesTopicsSubscriptionsRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` - FilterType *string `json:"filterType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CorrelationFilter *CorrelationFilter `json:"correlationFilter,omitempty"` + FilterType *string `json:"filterType,omitempty"` + OperatorSpec *NamespacesTopicsSubscriptionsRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -336,6 +360,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_From_Namesp // FilterType rule.FilterType = genruntime.ClonePointerToString(source.FilterType) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec NamespacesTopicsSubscriptionsRuleOperatorSpec + err := operatorSpec.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // OriginalVersion rule.OriginalVersion = source.OriginalVersion @@ -414,6 +450,18 @@ func (rule *NamespacesTopicsSubscriptionsRule_Spec) AssignProperties_To_Namespac // FilterType destination.FilterType = genruntime.ClonePointerToString(rule.FilterType) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion @@ -1162,6 +1210,136 @@ func (filter *CorrelationFilter_STATUS) AssignProperties_To_CorrelationFilter_ST return nil } +// Storage version of v1api20221001preview.NamespacesTopicsSubscriptionsRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type NamespacesTopicsSubscriptionsRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec populates our NamespacesTopicsSubscriptionsRuleOperatorSpec from the provided source NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(source *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec populates the provided destination NamespacesTopicsSubscriptionsRuleOperatorSpec from our NamespacesTopicsSubscriptionsRuleOperatorSpec +func (operator *NamespacesTopicsSubscriptionsRuleOperatorSpec) AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(destination *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20221001preview.SqlFilter // Represents a filter which is a composition of an expression and an action that is executed in the pub/sub pipeline. type SqlFilter struct { @@ -1356,6 +1534,11 @@ type augmentConversionForCorrelationFilter_STATUS interface { AssignPropertiesTo(dst *storage.CorrelationFilter_STATUS) error } +type augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec interface { + AssignPropertiesFrom(src *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error + AssignPropertiesTo(dst *storage.NamespacesTopicsSubscriptionsRuleOperatorSpec) error +} + type augmentConversionForSqlFilter interface { AssignPropertiesFrom(src *storage.SqlFilter) error AssignPropertiesTo(dst *storage.SqlFilter) error diff --git a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go index 866d28d376c..842f23ec77d 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go +++ b/v2/api/servicebus/v1api20221001preview/storage/namespaces_topics_subscriptions_rule_types_gen_test.go @@ -600,6 +600,103 @@ func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule(gens map[s gens["Status"] = NamespacesTopicsSubscriptionsRule_STATUSGenerator() } +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from NamespacesTopicsSubscriptionsRuleOperatorSpec to NamespacesTopicsSubscriptionsRuleOperatorSpec via AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec & AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec tests if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.NamespacesTopicsSubscriptionsRuleOperatorSpec + err := copied.AssignProperties_To_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = actual.AssignProperties_From_NamespacesTopicsSubscriptionsRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_NamespacesTopicsSubscriptionsRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of NamespacesTopicsSubscriptionsRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec, NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec runs a test to see if a specific instance of NamespacesTopicsSubscriptionsRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForNamespacesTopicsSubscriptionsRuleOperatorSpec(subject NamespacesTopicsSubscriptionsRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual NamespacesTopicsSubscriptionsRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing - lazily instantiated by +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() +var namespacesTopicsSubscriptionsRuleOperatorSpecGenerator gopter.Gen + +// NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator returns a generator of NamespacesTopicsSubscriptionsRuleOperatorSpec instances for property testing. +func NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator() gopter.Gen { + if namespacesTopicsSubscriptionsRuleOperatorSpecGenerator != nil { + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + namespacesTopicsSubscriptionsRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(NamespacesTopicsSubscriptionsRuleOperatorSpec{}), generators) + + return namespacesTopicsSubscriptionsRuleOperatorSpecGenerator +} + func Test_NamespacesTopicsSubscriptionsRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -842,6 +939,7 @@ func AddIndependentPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(g func AddRelatedPropertyGeneratorsForNamespacesTopicsSubscriptionsRule_Spec(gens map[string]gopter.Gen) { gens["Action"] = gen.PtrOf(ActionGenerator()) gens["CorrelationFilter"] = gen.PtrOf(CorrelationFilterGenerator()) + gens["OperatorSpec"] = gen.PtrOf(NamespacesTopicsSubscriptionsRuleOperatorSpecGenerator()) gens["SqlFilter"] = gen.PtrOf(SqlFilterGenerator()) } diff --git a/v2/api/servicebus/v1api20221001preview/storage/structure.txt b/v2/api/servicebus/v1api20221001preview/storage/structure.txt index a994494ba68..a44d5e8b9de 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/structure.txt +++ b/v2/api/servicebus/v1api20221001preview/storage/structure.txt @@ -29,8 +29,10 @@ Namespace: Resource │ │ └── Reference: genruntime.ResourceReference │ ├── Location: *string │ ├── MinimumTlsVersion: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (6 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -111,8 +113,10 @@ NamespacesAuthorizationRule: Resource ├── Owner: servicebus/v1api20221001preview.Namespace ├── Spec: Object (6 properties) │ ├── AzureName: string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -141,7 +145,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: servicebus/v1api20221001preview.Namespace -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DeadLetteringOnMessageExpiration: *bool @@ -156,6 +160,10 @@ NamespacesQueue: Resource │ ├── MaxDeliveryCount: *int │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -206,7 +214,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: servicebus/v1api20221001preview.Namespace -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── DefaultMessageTimeToLive: *string @@ -216,6 +224,10 @@ NamespacesTopic: Resource │ ├── EnablePartitioning: *bool │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -261,7 +273,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: servicebus/v1api20221001preview.NamespacesTopic -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: string │ ├── ClientAffineProperties: *Object (4 properties) @@ -279,6 +291,10 @@ NamespacesTopicsSubscription: Resource │ ├── IsClientAffine: *bool │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -329,7 +345,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: servicebus/v1api20221001preview.NamespacesTopicsSubscription -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── Action: *Object (4 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── PropertyBag: genruntime.PropertyBag @@ -349,6 +365,10 @@ NamespacesTopicsSubscriptionsRule: Resource │ │ ├── SessionId: *string │ │ └── To: *string │ ├── FilterType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -417,15 +437,19 @@ augmentConversionForNamespacesAuthorizationRuleOperatorSpec: Interface augmentConversionForNamespacesAuthorizationRule_STATUS: Interface augmentConversionForNamespacesAuthorizationRule_Spec: Interface augmentConversionForNamespacesQueue: Interface +augmentConversionForNamespacesQueueOperatorSpec: Interface augmentConversionForNamespacesQueue_STATUS: Interface augmentConversionForNamespacesQueue_Spec: Interface augmentConversionForNamespacesTopic: Interface +augmentConversionForNamespacesTopicOperatorSpec: Interface augmentConversionForNamespacesTopic_STATUS: Interface augmentConversionForNamespacesTopic_Spec: Interface augmentConversionForNamespacesTopicsSubscription: Interface +augmentConversionForNamespacesTopicsSubscriptionOperatorSpec: Interface augmentConversionForNamespacesTopicsSubscription_STATUS: Interface augmentConversionForNamespacesTopicsSubscription_Spec: Interface augmentConversionForNamespacesTopicsSubscriptionsRule: Interface +augmentConversionForNamespacesTopicsSubscriptionsRuleOperatorSpec: Interface augmentConversionForNamespacesTopicsSubscriptionsRule_STATUS: Interface augmentConversionForNamespacesTopicsSubscriptionsRule_Spec: Interface augmentConversionForPrivateEndpointConnection_STATUS: Interface diff --git a/v2/api/servicebus/v1api20221001preview/storage/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20221001preview/storage/zz_generated.deepcopy.go index 169a9b24110..36b158c95a2 100644 --- a/v2/api/servicebus/v1api20221001preview/storage/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20221001preview/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -633,6 +634,17 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -640,6 +652,17 @@ func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -993,6 +1016,17 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -1000,6 +1034,17 @@ func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesA (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1172,6 +1217,50 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1404,6 +1493,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1497,6 +1591,50 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1679,6 +1817,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1772,6 +1915,50 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1984,6 +2171,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2072,6 +2264,50 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -2164,6 +2400,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/servicebus/v1api20221001preview/structure.txt b/v2/api/servicebus/v1api20221001preview/structure.txt index 99a0c0f7015..5f943806db0 100644 --- a/v2/api/servicebus/v1api20221001preview/structure.txt +++ b/v2/api/servicebus/v1api20221001preview/structure.txt @@ -32,7 +32,9 @@ Namespace: Resource │ │ ├── "1.0" │ │ ├── "1.1" │ │ └── "1.2" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── Endpoint: *genruntime.SecretDestination │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination @@ -136,7 +138,9 @@ NamespacesAuthorizationRule: Resource │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 │ │ └── Rule 1: MinLength: 1 -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination @@ -174,7 +178,7 @@ NamespacesAuthorizationRule: Resource └── Type: *string NamespacesQueue: Resource ├── Owner: Namespace -├── Spec: Object (17 properties) +├── Spec: Object (18 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -190,6 +194,9 @@ NamespacesQueue: Resource │ ├── MaxDeliveryCount: *int │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── RequiresSession: *bool @@ -252,7 +259,7 @@ NamespacesQueue: Resource └── UpdatedAt: *string NamespacesTopic: Resource ├── Owner: Namespace -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (1 rule) │ │ └── Rule 0: MinLength: 1 @@ -263,6 +270,9 @@ NamespacesTopic: Resource │ ├── EnablePartitioning: *bool │ ├── MaxMessageSizeInKilobytes: *int │ ├── MaxSizeInMegabytes: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RequiresDuplicateDetection: *bool │ └── SupportOrdering: *bool @@ -320,7 +330,7 @@ NamespacesTopic: Resource └── UpdatedAt: *string NamespacesTopicsSubscription: Resource ├── Owner: NamespacesTopic -├── Spec: Object (15 properties) +├── Spec: Object (16 properties) │ ├── AutoDeleteOnIdle: *string │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 50 @@ -339,6 +349,9 @@ NamespacesTopicsSubscription: Resource │ ├── IsClientAffine: *bool │ ├── LockDuration: *string │ ├── MaxDeliveryCount: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RequiresSession: *bool └── Status: Object (25 properties) @@ -400,7 +413,7 @@ NamespacesTopicsSubscription: Resource └── UpdatedAt: *string NamespacesTopicsSubscriptionsRule: Resource ├── Owner: NamespacesTopicsSubscription -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Action: *Object (3 properties) │ │ ├── CompatibilityLevel: *int │ │ ├── RequiresPreprocessing: *bool @@ -422,6 +435,9 @@ NamespacesTopicsSubscriptionsRule: Resource │ ├── FilterType: *Enum (2 values) │ │ ├── "CorrelationFilter" │ │ └── "SqlFilter" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── SqlFilter: *Object (3 properties) │ ├── CompatibilityLevel: *int diff --git a/v2/api/servicebus/v1api20221001preview/zz_generated.deepcopy.go b/v2/api/servicebus/v1api20221001preview/zz_generated.deepcopy.go index d5abde14991..573d3cc50b7 100644 --- a/v2/api/servicebus/v1api20221001preview/zz_generated.deepcopy.go +++ b/v2/api/servicebus/v1api20221001preview/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20221001preview import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -547,6 +548,28 @@ func (in *NamespaceOperatorSecrets) DeepCopy() *NamespaceOperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceOperatorSpec) DeepCopyInto(out *NamespaceOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespaceOperatorSecrets) @@ -879,6 +902,28 @@ func (in *NamespacesAuthorizationRuleOperatorSecrets) DeepCopy() *NamespacesAuth // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesAuthorizationRuleOperatorSpec) DeepCopyInto(out *NamespacesAuthorizationRuleOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(NamespacesAuthorizationRuleOperatorSecrets) @@ -1037,6 +1082,43 @@ func (in *NamespacesQueueList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesQueueOperatorSpec) DeepCopyInto(out *NamespacesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesQueueOperatorSpec. +func (in *NamespacesQueueOperatorSpec) DeepCopy() *NamespacesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesQueue_STATUS) DeepCopyInto(out *NamespacesQueue_STATUS) { *out = *in @@ -1262,6 +1344,11 @@ func (in *NamespacesQueue_Spec) DeepCopyInto(out *NamespacesQueue_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1348,6 +1435,43 @@ func (in *NamespacesTopicList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicOperatorSpec) DeepCopyInto(out *NamespacesTopicOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicOperatorSpec. +func (in *NamespacesTopicOperatorSpec) DeepCopy() *NamespacesTopicOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopic_STATUS) DeepCopyInto(out *NamespacesTopic_STATUS) { *out = *in @@ -1523,6 +1647,11 @@ func (in *NamespacesTopic_Spec) DeepCopyInto(out *NamespacesTopic_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1609,6 +1738,43 @@ func (in *NamespacesTopicsSubscriptionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionOperatorSpec. +func (in *NamespacesTopicsSubscriptionOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscription_STATUS) DeepCopyInto(out *NamespacesTopicsSubscription_STATUS) { *out = *in @@ -1814,6 +1980,11 @@ func (in *NamespacesTopicsSubscription_Spec) DeepCopyInto(out *NamespacesTopicsS *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1895,6 +2066,43 @@ func (in *NamespacesTopicsSubscriptionsRuleList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopyInto(out *NamespacesTopicsSubscriptionsRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacesTopicsSubscriptionsRuleOperatorSpec. +func (in *NamespacesTopicsSubscriptionsRuleOperatorSpec) DeepCopy() *NamespacesTopicsSubscriptionsRuleOperatorSpec { + if in == nil { + return nil + } + out := new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespacesTopicsSubscriptionsRule_STATUS) DeepCopyInto(out *NamespacesTopicsSubscriptionsRule_STATUS) { *out = *in @@ -1980,6 +2188,11 @@ func (in *NamespacesTopicsSubscriptionsRule_Spec) DeepCopyInto(out *NamespacesTo *out = new(FilterType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(NamespacesTopicsSubscriptionsRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/signalrservice/v1api20211001/signal_r_types_gen.go b/v2/api/signalrservice/v1api20211001/signal_r_types_gen.go index f2c37d89ca2..14443a0a5c7 100644 --- a/v2/api/signalrservice/v1api20211001/signal_r_types_gen.go +++ b/v2/api/signalrservice/v1api20211001/signal_r_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -92,6 +94,26 @@ func (signalR *SignalR) defaultAzureName() { // defaultImpl applies the code generated defaults to the SignalR resource func (signalR *SignalR) defaultImpl() { signalR.defaultAzureName() } +var _ configmaps.Exporter = &SignalR{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (signalR *SignalR) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if signalR.Spec.OperatorSpec == nil { + return nil + } + return signalR.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SignalR{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (signalR *SignalR) SecretDestinationExpressions() []*core.DestinationExpression { + if signalR.Spec.OperatorSpec == nil { + return nil + } + return signalR.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &SignalR{} // InitializeSpec initializes the spec for this resource from the given status @@ -210,7 +232,7 @@ func (signalR *SignalR) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (signalR *SignalR) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){signalR.validateResourceReferences, signalR.validateOwnerReference, signalR.validateSecretDestinations} + return []func() (admission.Warnings, error){signalR.validateResourceReferences, signalR.validateOwnerReference, signalR.validateSecretDestinations, signalR.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -231,7 +253,18 @@ func (signalR *SignalR) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return signalR.validateSecretDestinations() }, + func(old runtime.Object) (admission.Warnings, error) { + return signalR.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (signalR *SignalR) validateConfigMapDestinations() (admission.Warnings, error) { + if signalR.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(signalR, nil, signalR.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -253,16 +286,16 @@ func (signalR *SignalR) validateSecretDestinations() (admission.Warnings, error) if signalR.Spec.OperatorSpec == nil { return nil, nil } - if signalR.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - signalR.Spec.OperatorSpec.Secrets.PrimaryConnectionString, - signalR.Spec.OperatorSpec.Secrets.PrimaryKey, - signalR.Spec.OperatorSpec.Secrets.SecondaryConnectionString, - signalR.Spec.OperatorSpec.Secrets.SecondaryKey, + var toValidate []*genruntime.SecretDestination + if signalR.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + signalR.Spec.OperatorSpec.Secrets.PrimaryConnectionString, + signalR.Spec.OperatorSpec.Secrets.PrimaryKey, + signalR.Spec.OperatorSpec.Secrets.SecondaryConnectionString, + signalR.Spec.OperatorSpec.Secrets.SecondaryKey, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(signalR, toValidate, signalR.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -4272,6 +4305,12 @@ func (acLs *SignalRNetworkACLs_STATUS) AssignProperties_To_SignalRNetworkACLs_ST // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SignalROperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *SignalROperatorSecrets `json:"secrets,omitempty"` } @@ -4279,6 +4318,42 @@ type SignalROperatorSpec struct { // AssignProperties_From_SignalROperatorSpec populates our SignalROperatorSpec from the provided source SignalROperatorSpec func (operator *SignalROperatorSpec) AssignProperties_From_SignalROperatorSpec(source *storage.SignalROperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret SignalROperatorSecrets @@ -4300,6 +4375,42 @@ func (operator *SignalROperatorSpec) AssignProperties_To_SignalROperatorSpec(des // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.SignalROperatorSecrets diff --git a/v2/api/signalrservice/v1api20211001/storage/signal_r_types_gen.go b/v2/api/signalrservice/v1api20211001/storage/signal_r_types_gen.go index 2bbba9e8813..bfe68975542 100644 --- a/v2/api/signalrservice/v1api20211001/storage/signal_r_types_gen.go +++ b/v2/api/signalrservice/v1api20211001/storage/signal_r_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (signalR *SignalR) SetConditions(conditions conditions.Conditions) { signalR.Status.Conditions = conditions } +var _ configmaps.Exporter = &SignalR{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (signalR *SignalR) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if signalR.Spec.OperatorSpec == nil { + return nil + } + return signalR.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &SignalR{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (signalR *SignalR) SecretDestinationExpressions() []*core.DestinationExpression { + if signalR.Spec.OperatorSpec == nil { + return nil + } + return signalR.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &SignalR{} // AzureName returns the Azure name of the resource @@ -380,8 +403,10 @@ type SignalRNetworkACLs_STATUS struct { // Storage version of v1api20211001.SignalROperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type SignalROperatorSpec struct { - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *SignalROperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *SignalROperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20211001.SignalRTlsSettings diff --git a/v2/api/signalrservice/v1api20211001/storage/structure.txt b/v2/api/signalrservice/v1api20211001/storage/structure.txt index af8fca107f1..dac4a756fd5 100644 --- a/v2/api/signalrservice/v1api20211001/storage/structure.txt +++ b/v2/api/signalrservice/v1api20211001/storage/structure.txt @@ -37,8 +37,10 @@ SignalR: Resource │ │ ├── Allow: string[] │ │ ├── Deny: string[] │ │ └── PropertyBag: genruntime.PropertyBag -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (5 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination diff --git a/v2/api/signalrservice/v1api20211001/storage/zz_generated.deepcopy.go b/v2/api/signalrservice/v1api20211001/storage/zz_generated.deepcopy.go index 8a0b56d8031..f655989699f 100644 --- a/v2/api/signalrservice/v1api20211001/storage/zz_generated.deepcopy.go +++ b/v2/api/signalrservice/v1api20211001/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -917,6 +918,17 @@ func (in *SignalROperatorSecrets) DeepCopy() *SignalROperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SignalROperatorSpec) DeepCopyInto(out *SignalROperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.PropertyBag != nil { in, out := &in.PropertyBag, &out.PropertyBag *out = make(genruntime.PropertyBag, len(*in)) @@ -924,6 +936,17 @@ func (in *SignalROperatorSpec) DeepCopyInto(out *SignalROperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SignalROperatorSecrets) diff --git a/v2/api/signalrservice/v1api20211001/structure.txt b/v2/api/signalrservice/v1api20211001/structure.txt index a392a3b194e..4906e613a12 100644 --- a/v2/api/signalrservice/v1api20211001/structure.txt +++ b/v2/api/signalrservice/v1api20211001/structure.txt @@ -59,7 +59,9 @@ SignalR: Resource │ │ ├── "RESTAPI" │ │ ├── "ServerConnection" │ │ └── "Trace" -│ ├── OperatorSpec: *Object (1 property) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (4 properties) │ │ ├── PrimaryConnectionString: *genruntime.SecretDestination │ │ ├── PrimaryKey: *genruntime.SecretDestination diff --git a/v2/api/signalrservice/v1api20211001/zz_generated.deepcopy.go b/v2/api/signalrservice/v1api20211001/zz_generated.deepcopy.go index 9ffcd387815..cfb74a81a49 100644 --- a/v2/api/signalrservice/v1api20211001/zz_generated.deepcopy.go +++ b/v2/api/signalrservice/v1api20211001/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20211001 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -740,6 +741,28 @@ func (in *SignalROperatorSecrets) DeepCopy() *SignalROperatorSecrets { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SignalROperatorSpec) DeepCopyInto(out *SignalROperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(SignalROperatorSecrets) diff --git a/v2/api/sql/v1api20211101/server_types_gen.go b/v2/api/sql/v1api20211101/server_types_gen.go index 5653f351433..b87b5a2ccc3 100644 --- a/v2/api/sql/v1api20211101/server_types_gen.go +++ b/v2/api/sql/v1api20211101/server_types_gen.go @@ -13,6 +13,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -96,6 +98,26 @@ func (server *Server) defaultAzureName() { // defaultImpl applies the code generated defaults to the Server resource func (server *Server) defaultImpl() { server.defaultAzureName() } +var _ configmaps.Exporter = &Server{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *Server) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Server{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *Server) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Server{} // InitializeSpec initializes the spec for this resource from the given status @@ -231,7 +253,7 @@ func (server *Server) ValidateUpdate(old runtime.Object) (admission.Warnings, er // createValidations validates the creation of the resource func (server *Server) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateConfigMapDestinations} + return []func() (admission.Warnings, error){server.validateResourceReferences, server.validateOwnerReference, server.validateSecretDestinations, server.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -249,6 +271,9 @@ func (server *Server) updateValidations() []func(old runtime.Object) (admission. func(old runtime.Object) (admission.Warnings, error) { return server.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return server.validateSecretDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return server.validateConfigMapDestinations() }, @@ -260,13 +285,13 @@ func (server *Server) validateConfigMapDestinations() (admission.Warnings, error if server.Spec.OperatorSpec == nil { return nil, nil } - if server.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + var toValidate []*genruntime.ConfigMapDestination + if server.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + server.Spec.OperatorSpec.ConfigMaps.FullyQualifiedDomainName, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(server, toValidate, server.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -283,6 +308,14 @@ func (server *Server) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (server *Server) validateSecretDestinations() (admission.Warnings, error) { + if server.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(server, nil, server.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (server *Server) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Server) @@ -2404,13 +2437,37 @@ func (administrator *ServerExternalAdministrator_STATUS) AssignProperties_To_Ser // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ServerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *ServerOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // AssignProperties_From_ServerOperatorSpec populates our ServerOperatorSpec from the provided source ServerOperatorSpec func (operator *ServerOperatorSpec) AssignProperties_From_ServerOperatorSpec(source *storage.ServerOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap ServerOperatorConfigMaps @@ -2423,6 +2480,24 @@ func (operator *ServerOperatorSpec) AssignProperties_From_ServerOperatorSpec(sou operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // No error return nil } @@ -2432,6 +2507,24 @@ func (operator *ServerOperatorSpec) AssignProperties_To_ServerOperatorSpec(desti // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.ServerOperatorConfigMaps @@ -2444,6 +2537,24 @@ func (operator *ServerOperatorSpec) AssignProperties_To_ServerOperatorSpec(desti destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Update the property bag if len(propertyBag) > 0 { destination.PropertyBag = propertyBag diff --git a/v2/api/sql/v1api20211101/servers_administrator_types_gen.go b/v2/api/sql/v1api20211101/servers_administrator_types_gen.go index e2e013ef413..4704d25d5d6 100644 --- a/v2/api/sql/v1api20211101/servers_administrator_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_administrator_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (administrator *ServersAdministrator) Default() { // defaultImpl applies the code generated defaults to the ServersAdministrator resource func (administrator *ServersAdministrator) defaultImpl() {} +var _ configmaps.Exporter = &ServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *ServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *ServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersAdministrator{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +225,7 @@ func (administrator *ServersAdministrator) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (administrator *ServersAdministrator) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){administrator.validateResourceReferences, administrator.validateOwnerReference, administrator.validateSecretDestinations, administrator.validateConfigMapDestinations, administrator.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -221,12 +243,26 @@ func (administrator *ServersAdministrator) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return administrator.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return administrator.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (administrator *ServersAdministrator) validateConfigMapDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (administrator *ServersAdministrator) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&administrator.Spec) @@ -250,6 +286,14 @@ func (administrator *ServersAdministrator) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (administrator *ServersAdministrator) validateSecretDestinations() (admission.Warnings, error) { + if administrator.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(administrator, nil, administrator.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (administrator *ServersAdministrator) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersAdministrator) @@ -340,6 +384,10 @@ type ServersAdministrator_Spec struct { // Login: Login name of the server administrator. Login *string `json:"login,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -451,6 +499,8 @@ func (administrator *ServersAdministrator_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": administrator.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -548,6 +598,18 @@ func (administrator *ServersAdministrator_Spec) AssignProperties_From_ServersAdm // Login administrator.Login = genruntime.ClonePointerToString(source.Login) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersAdministratorOperatorSpec + err := operatorSpec.AssignProperties_From_ServersAdministratorOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + administrator.OperatorSpec = &operatorSpec + } else { + administrator.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -608,6 +670,18 @@ func (administrator *ServersAdministrator_Spec) AssignProperties_To_ServersAdmin // Login destination.Login = genruntime.ClonePointerToString(administrator.Login) + // OperatorSpec + if administrator.OperatorSpec != nil { + var operatorSpec storage.ServersAdministratorOperatorSpec + err := administrator.OperatorSpec.AssignProperties_To_ServersAdministratorOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersAdministratorOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = administrator.OriginalVersion() @@ -982,6 +1056,110 @@ var administratorProperties_AdministratorType_STATUS_Values = map[string]Adminis "activedirectory": AdministratorProperties_AdministratorType_STATUS_ActiveDirectory, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAdministratorOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersAdministratorOperatorSpec populates our ServersAdministratorOperatorSpec from the provided source ServersAdministratorOperatorSpec +func (operator *ServersAdministratorOperatorSpec) AssignProperties_From_ServersAdministratorOperatorSpec(source *storage.ServersAdministratorOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersAdministratorOperatorSpec populates the provided destination ServersAdministratorOperatorSpec from our ServersAdministratorOperatorSpec +func (operator *ServersAdministratorOperatorSpec) AssignProperties_To_ServersAdministratorOperatorSpec(destination *storage.ServersAdministratorOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersAdministrator{}, &ServersAdministratorList{}) } diff --git a/v2/api/sql/v1api20211101/servers_administrator_types_gen_test.go b/v2/api/sql/v1api20211101/servers_administrator_types_gen_test.go index 57882357bb8..a067a6d9c0a 100644 --- a/v2/api/sql/v1api20211101/servers_administrator_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_administrator_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersAdministrator(gens map[string]gopter. gens["Status"] = ServersAdministrator_STATUSGenerator() } +func Test_ServersAdministratorOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersAdministratorOperatorSpec to ServersAdministratorOperatorSpec via AssignProperties_To_ServersAdministratorOperatorSpec & AssignProperties_From_ServersAdministratorOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersAdministratorOperatorSpec, ServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersAdministratorOperatorSpec tests if a specific instance of ServersAdministratorOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersAdministratorOperatorSpec(subject ServersAdministratorOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersAdministratorOperatorSpec + err := copied.AssignProperties_To_ServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersAdministratorOperatorSpec + err = actual.AssignProperties_From_ServersAdministratorOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAdministratorOperatorSpec, ServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAdministratorOperatorSpec runs a test to see if a specific instance of ServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAdministratorOperatorSpec(subject ServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// ServersAdministratorOperatorSpecGenerator() +var serversAdministratorOperatorSpecGenerator gopter.Gen + +// ServersAdministratorOperatorSpecGenerator returns a generator of ServersAdministratorOperatorSpec instances for property testing. +func ServersAdministratorOperatorSpecGenerator() gopter.Gen { + if serversAdministratorOperatorSpecGenerator != nil { + return serversAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministratorOperatorSpec{}), generators) + + return serversAdministratorOperatorSpecGenerator +} + func Test_ServersAdministrator_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForServersAdministrator_Spec(subject ServersAdminis var serversAdministrator_SpecGenerator gopter.Gen // ServersAdministrator_SpecGenerator returns a generator of ServersAdministrator_Spec instances for property testing. +// We first initialize serversAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAdministrator_SpecGenerator() gopter.Gen { if serversAdministrator_SpecGenerator != nil { return serversAdministrator_SpecGenerator @@ -370,6 +470,12 @@ func ServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAdministrator_Spec(generators) serversAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForServersAdministrator_Spec(generators) + serversAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministrator_Spec{}), generators) + return serversAdministrator_SpecGenerator } @@ -380,3 +486,8 @@ func AddIndependentPropertyGeneratorsForServersAdministrator_Spec(gens map[strin gens["Sid"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAdministratorOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen.go b/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen.go index 7716086cac3..7a6182233f3 100644 --- a/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *ServersAdvancedThreatProtectionSetting) Default() { // defaultImpl applies the code generated defaults to the ServersAdvancedThreatProtectionSetting resource func (setting *ServersAdvancedThreatProtectionSetting) defaultImpl() {} +var _ configmaps.Exporter = &ServersAdvancedThreatProtectionSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersAdvancedThreatProtectionSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAdvancedThreatProtectionSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersAdvancedThreatProtectionSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersAdvancedThreatProtectionSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *ServersAdvancedThreatProtectionSetting) ValidateUpdate(old runtim // createValidations validates the creation of the resource func (setting *ServersAdvancedThreatProtectionSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *ServersAdvancedThreatProtectionSetting) updateValidations() []fun func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *ServersAdvancedThreatProtectionSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *ServersAdvancedThreatProtectionSetting) validateResourceReference return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *ServersAdvancedThreatProtectionSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *ServersAdvancedThreatProtectionSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersAdvancedThreatProtectionSetting) @@ -318,6 +363,10 @@ type ServersAdvancedThreatProtectionSettingList struct { } type ServersAdvancedThreatProtectionSetting_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersAdvancedThreatProtectionSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -367,6 +416,8 @@ func (setting *ServersAdvancedThreatProtectionSetting_Spec) PopulateFromARM(owne return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.ServersAdvancedThreatProtectionSetting_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -441,6 +492,18 @@ func (setting *ServersAdvancedThreatProtectionSetting_Spec) ConvertSpecTo(destin // AssignProperties_From_ServersAdvancedThreatProtectionSetting_Spec populates our ServersAdvancedThreatProtectionSetting_Spec from the provided source ServersAdvancedThreatProtectionSetting_Spec func (setting *ServersAdvancedThreatProtectionSetting_Spec) AssignProperties_From_ServersAdvancedThreatProtectionSetting_Spec(source *storage.ServersAdvancedThreatProtectionSetting_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersAdvancedThreatProtectionSettingOperatorSpec + err := operatorSpec.AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -467,6 +530,18 @@ func (setting *ServersAdvancedThreatProtectionSetting_Spec) AssignProperties_To_ // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.ServersAdvancedThreatProtectionSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -785,6 +860,110 @@ var advancedThreatProtectionProperties_State_STATUS_Values = map[string]Advanced "new": AdvancedThreatProtectionProperties_State_STATUS_New, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAdvancedThreatProtectionSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec populates our ServersAdvancedThreatProtectionSettingOperatorSpec from the provided source ServersAdvancedThreatProtectionSettingOperatorSpec +func (operator *ServersAdvancedThreatProtectionSettingOperatorSpec) AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec(source *storage.ServersAdvancedThreatProtectionSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec populates the provided destination ServersAdvancedThreatProtectionSettingOperatorSpec from our ServersAdvancedThreatProtectionSettingOperatorSpec +func (operator *ServersAdvancedThreatProtectionSettingOperatorSpec) AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec(destination *storage.ServersAdvancedThreatProtectionSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { // CreatedAt: The timestamp of resource creation (UTC). diff --git a/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen_test.go b/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen_test.go index 4484914ad2f..6944dbf593d 100644 --- a/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_advanced_threat_protection_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting(gens gens["Status"] = ServersAdvancedThreatProtectionSetting_STATUSGenerator() } +func Test_ServersAdvancedThreatProtectionSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersAdvancedThreatProtectionSettingOperatorSpec to ServersAdvancedThreatProtectionSettingOperatorSpec via AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec & AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersAdvancedThreatProtectionSettingOperatorSpec, ServersAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersAdvancedThreatProtectionSettingOperatorSpec tests if a specific instance of ServersAdvancedThreatProtectionSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersAdvancedThreatProtectionSettingOperatorSpec(subject ServersAdvancedThreatProtectionSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersAdvancedThreatProtectionSettingOperatorSpec + err := copied.AssignProperties_To_ServersAdvancedThreatProtectionSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersAdvancedThreatProtectionSettingOperatorSpec + err = actual.AssignProperties_From_ServersAdvancedThreatProtectionSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersAdvancedThreatProtectionSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAdvancedThreatProtectionSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec, ServersAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec runs a test to see if a specific instance of ServersAdvancedThreatProtectionSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec(subject ServersAdvancedThreatProtectionSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAdvancedThreatProtectionSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAdvancedThreatProtectionSettingOperatorSpec instances for property testing - lazily instantiated +// by ServersAdvancedThreatProtectionSettingOperatorSpecGenerator() +var serversAdvancedThreatProtectionSettingOperatorSpecGenerator gopter.Gen + +// ServersAdvancedThreatProtectionSettingOperatorSpecGenerator returns a generator of ServersAdvancedThreatProtectionSettingOperatorSpec instances for property testing. +func ServersAdvancedThreatProtectionSettingOperatorSpecGenerator() gopter.Gen { + if serversAdvancedThreatProtectionSettingOperatorSpecGenerator != nil { + return serversAdvancedThreatProtectionSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAdvancedThreatProtectionSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSettingOperatorSpec{}), generators) + + return serversAdvancedThreatProtectionSettingOperatorSpecGenerator +} + func Test_ServersAdvancedThreatProtectionSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForServersAdvancedThreatProtectionSetting_Spec(subj var serversAdvancedThreatProtectionSetting_SpecGenerator gopter.Gen // ServersAdvancedThreatProtectionSetting_SpecGenerator returns a generator of ServersAdvancedThreatProtectionSetting_Spec instances for property testing. +// We first initialize serversAdvancedThreatProtectionSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { if serversAdvancedThreatProtectionSetting_SpecGenerator != nil { return serversAdvancedThreatProtectionSetting_SpecGenerator @@ -381,6 +481,12 @@ func ServersAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) serversAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) + serversAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSetting_Spec{}), generators) + return serversAdvancedThreatProtectionSetting_SpecGenerator } @@ -389,6 +495,11 @@ func AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_S gens["State"] = gen.PtrOf(gen.OneConstOf(AdvancedThreatProtectionProperties_State_Disabled, AdvancedThreatProtectionProperties_State_Enabled, AdvancedThreatProtectionProperties_State_New)) } +// AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAdvancedThreatProtectionSettingOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen.go b/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen.go index e8c4f021f25..318c82af525 100644 --- a/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *ServersAuditingSetting) Default() { // defaultImpl applies the code generated defaults to the ServersAuditingSetting resource func (setting *ServersAuditingSetting) defaultImpl() {} +var _ configmaps.Exporter = &ServersAuditingSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersAuditingSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAuditingSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersAuditingSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersAuditingSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *ServersAuditingSetting) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (setting *ServersAuditingSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *ServersAuditingSetting) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *ServersAuditingSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *ServersAuditingSetting) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *ServersAuditingSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *ServersAuditingSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersAuditingSetting) @@ -407,6 +452,10 @@ type ServersAuditingSetting_Spec struct { // IsStorageSecondaryKeyInUse: Specifies whether storageAccountAccessKey value is the storage's secondary key. IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersAuditingSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -580,6 +629,8 @@ func (setting *ServersAuditingSetting_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -727,6 +778,18 @@ func (setting *ServersAuditingSetting_Spec) AssignProperties_From_ServersAuditin setting.IsStorageSecondaryKeyInUse = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersAuditingSettingOperatorSpec + err := operatorSpec.AssignProperties_From_ServersAuditingSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersAuditingSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -813,6 +876,18 @@ func (setting *ServersAuditingSetting_Spec) AssignProperties_To_ServersAuditingS destination.IsStorageSecondaryKeyInUse = nil } + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.ServersAuditingSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_ServersAuditingSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersAuditingSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -1426,6 +1501,110 @@ var serverBlobAuditingPolicyProperties_State_STATUS_Values = map[string]ServerBl "enabled": ServerBlobAuditingPolicyProperties_State_STATUS_Enabled, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAuditingSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersAuditingSettingOperatorSpec populates our ServersAuditingSettingOperatorSpec from the provided source ServersAuditingSettingOperatorSpec +func (operator *ServersAuditingSettingOperatorSpec) AssignProperties_From_ServersAuditingSettingOperatorSpec(source *storage.ServersAuditingSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersAuditingSettingOperatorSpec populates the provided destination ServersAuditingSettingOperatorSpec from our ServersAuditingSettingOperatorSpec +func (operator *ServersAuditingSettingOperatorSpec) AssignProperties_To_ServersAuditingSettingOperatorSpec(destination *storage.ServersAuditingSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersAuditingSetting{}, &ServersAuditingSettingList{}) } diff --git a/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen_test.go b/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen_test.go index 4149051cc87..162c9bb6073 100644 --- a/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_auditing_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersAuditingSetting(gens map[string]gopte gens["Status"] = ServersAuditingSetting_STATUSGenerator() } +func Test_ServersAuditingSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersAuditingSettingOperatorSpec to ServersAuditingSettingOperatorSpec via AssignProperties_To_ServersAuditingSettingOperatorSpec & AssignProperties_From_ServersAuditingSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersAuditingSettingOperatorSpec, ServersAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersAuditingSettingOperatorSpec tests if a specific instance of ServersAuditingSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersAuditingSettingOperatorSpec(subject ServersAuditingSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersAuditingSettingOperatorSpec + err := copied.AssignProperties_To_ServersAuditingSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersAuditingSettingOperatorSpec + err = actual.AssignProperties_From_ServersAuditingSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersAuditingSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAuditingSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAuditingSettingOperatorSpec, ServersAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAuditingSettingOperatorSpec runs a test to see if a specific instance of ServersAuditingSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAuditingSettingOperatorSpec(subject ServersAuditingSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAuditingSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAuditingSettingOperatorSpec instances for property testing - lazily instantiated by +// ServersAuditingSettingOperatorSpecGenerator() +var serversAuditingSettingOperatorSpecGenerator gopter.Gen + +// ServersAuditingSettingOperatorSpecGenerator returns a generator of ServersAuditingSettingOperatorSpec instances for property testing. +func ServersAuditingSettingOperatorSpecGenerator() gopter.Gen { + if serversAuditingSettingOperatorSpecGenerator != nil { + return serversAuditingSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAuditingSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSettingOperatorSpec{}), generators) + + return serversAuditingSettingOperatorSpecGenerator +} + func Test_ServersAuditingSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -366,6 +463,9 @@ func RunJSONSerializationTestForServersAuditingSetting_Spec(subject ServersAudit var serversAuditingSetting_SpecGenerator gopter.Gen // ServersAuditingSetting_SpecGenerator returns a generator of ServersAuditingSetting_Spec instances for property testing. +// We first initialize serversAuditingSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAuditingSetting_SpecGenerator() gopter.Gen { if serversAuditingSetting_SpecGenerator != nil { return serversAuditingSetting_SpecGenerator @@ -375,6 +475,12 @@ func ServersAuditingSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(generators) serversAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec(generators) + serversAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSetting_Spec{}), generators) + return serversAuditingSetting_SpecGenerator } @@ -391,3 +497,8 @@ func AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(gens map[str gens["StorageAccountSubscriptionId"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAuditingSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen.go b/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen.go index b5d3585a70c..b0352e0c21f 100644 --- a/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (authentication *ServersAzureADOnlyAuthentication) Default() { // defaultImpl applies the code generated defaults to the ServersAzureADOnlyAuthentication resource func (authentication *ServersAzureADOnlyAuthentication) defaultImpl() {} +var _ configmaps.Exporter = &ServersAzureADOnlyAuthentication{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authentication *ServersAzureADOnlyAuthentication) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authentication.Spec.OperatorSpec == nil { + return nil + } + return authentication.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAzureADOnlyAuthentication{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authentication *ServersAzureADOnlyAuthentication) SecretDestinationExpressions() []*core.DestinationExpression { + if authentication.Spec.OperatorSpec == nil { + return nil + } + return authentication.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersAzureADOnlyAuthentication{} // InitializeSpec initializes the spec for this resource from the given status @@ -202,7 +225,7 @@ func (authentication *ServersAzureADOnlyAuthentication) ValidateUpdate(old runti // createValidations validates the creation of the resource func (authentication *ServersAzureADOnlyAuthentication) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){authentication.validateResourceReferences, authentication.validateOwnerReference} + return []func() (admission.Warnings, error){authentication.validateResourceReferences, authentication.validateOwnerReference, authentication.validateSecretDestinations, authentication.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -220,9 +243,23 @@ func (authentication *ServersAzureADOnlyAuthentication) updateValidations() []fu func(old runtime.Object) (admission.Warnings, error) { return authentication.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return authentication.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return authentication.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (authentication *ServersAzureADOnlyAuthentication) validateConfigMapDestinations() (admission.Warnings, error) { + if authentication.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(authentication, nil, authentication.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (authentication *ServersAzureADOnlyAuthentication) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(authentication) @@ -237,6 +274,14 @@ func (authentication *ServersAzureADOnlyAuthentication) validateResourceReferenc return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (authentication *ServersAzureADOnlyAuthentication) validateSecretDestinations() (admission.Warnings, error) { + if authentication.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(authentication, nil, authentication.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (authentication *ServersAzureADOnlyAuthentication) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersAzureADOnlyAuthentication) @@ -323,6 +368,10 @@ type ServersAzureADOnlyAuthentication_Spec struct { // AzureADOnlyAuthentication: Azure Active Directory only Authentication enabled. AzureADOnlyAuthentication *bool `json:"azureADOnlyAuthentication,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersAzureADOnlyAuthenticationOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -374,6 +423,8 @@ func (authentication *ServersAzureADOnlyAuthentication_Spec) PopulateFromARM(own } } + // no assignment for property "OperatorSpec" + // Set property "Owner": authentication.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -445,6 +496,18 @@ func (authentication *ServersAzureADOnlyAuthentication_Spec) AssignProperties_Fr authentication.AzureADOnlyAuthentication = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersAzureADOnlyAuthenticationOperatorSpec + err := operatorSpec.AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec() to populate field OperatorSpec") + } + authentication.OperatorSpec = &operatorSpec + } else { + authentication.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -470,6 +533,18 @@ func (authentication *ServersAzureADOnlyAuthentication_Spec) AssignProperties_To destination.AzureADOnlyAuthentication = nil } + // OperatorSpec + if authentication.OperatorSpec != nil { + var operatorSpec storage.ServersAzureADOnlyAuthenticationOperatorSpec + err := authentication.OperatorSpec.AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = authentication.OriginalVersion() @@ -689,6 +764,110 @@ func (authentication *ServersAzureADOnlyAuthentication_STATUS) AssignProperties_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAzureADOnlyAuthenticationOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec populates our ServersAzureADOnlyAuthenticationOperatorSpec from the provided source ServersAzureADOnlyAuthenticationOperatorSpec +func (operator *ServersAzureADOnlyAuthenticationOperatorSpec) AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec(source *storage.ServersAzureADOnlyAuthenticationOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec populates the provided destination ServersAzureADOnlyAuthenticationOperatorSpec from our ServersAzureADOnlyAuthenticationOperatorSpec +func (operator *ServersAzureADOnlyAuthenticationOperatorSpec) AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec(destination *storage.ServersAzureADOnlyAuthenticationOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersAzureADOnlyAuthentication{}, &ServersAzureADOnlyAuthenticationList{}) } diff --git a/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen_test.go b/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen_test.go index dabe9549829..aba95ca92ea 100644 --- a/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_azure_ad_only_authentication_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication(gens map[st gens["Status"] = ServersAzureADOnlyAuthentication_STATUSGenerator() } +func Test_ServersAzureADOnlyAuthenticationOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersAzureADOnlyAuthenticationOperatorSpec to ServersAzureADOnlyAuthenticationOperatorSpec via AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec & AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersAzureADOnlyAuthenticationOperatorSpec, ServersAzureADOnlyAuthenticationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersAzureADOnlyAuthenticationOperatorSpec tests if a specific instance of ServersAzureADOnlyAuthenticationOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersAzureADOnlyAuthenticationOperatorSpec(subject ServersAzureADOnlyAuthenticationOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersAzureADOnlyAuthenticationOperatorSpec + err := copied.AssignProperties_To_ServersAzureADOnlyAuthenticationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersAzureADOnlyAuthenticationOperatorSpec + err = actual.AssignProperties_From_ServersAzureADOnlyAuthenticationOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersAzureADOnlyAuthenticationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAzureADOnlyAuthenticationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec, ServersAzureADOnlyAuthenticationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec runs a test to see if a specific instance of ServersAzureADOnlyAuthenticationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec(subject ServersAzureADOnlyAuthenticationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAzureADOnlyAuthenticationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAzureADOnlyAuthenticationOperatorSpec instances for property testing - lazily instantiated by +// ServersAzureADOnlyAuthenticationOperatorSpecGenerator() +var serversAzureADOnlyAuthenticationOperatorSpecGenerator gopter.Gen + +// ServersAzureADOnlyAuthenticationOperatorSpecGenerator returns a generator of ServersAzureADOnlyAuthenticationOperatorSpec instances for property testing. +func ServersAzureADOnlyAuthenticationOperatorSpecGenerator() gopter.Gen { + if serversAzureADOnlyAuthenticationOperatorSpecGenerator != nil { + return serversAzureADOnlyAuthenticationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAzureADOnlyAuthenticationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthenticationOperatorSpec{}), generators) + + return serversAzureADOnlyAuthenticationOperatorSpecGenerator +} + func Test_ServersAzureADOnlyAuthentication_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -357,6 +454,9 @@ func RunJSONSerializationTestForServersAzureADOnlyAuthentication_Spec(subject Se var serversAzureADOnlyAuthentication_SpecGenerator gopter.Gen // ServersAzureADOnlyAuthentication_SpecGenerator returns a generator of ServersAzureADOnlyAuthentication_Spec instances for property testing. +// We first initialize serversAzureADOnlyAuthentication_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAzureADOnlyAuthentication_SpecGenerator() gopter.Gen { if serversAzureADOnlyAuthentication_SpecGenerator != nil { return serversAzureADOnlyAuthentication_SpecGenerator @@ -366,6 +466,12 @@ func ServersAzureADOnlyAuthentication_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) serversAzureADOnlyAuthentication_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthentication_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) + AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) + serversAzureADOnlyAuthentication_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthentication_Spec{}), generators) + return serversAzureADOnlyAuthentication_SpecGenerator } @@ -373,3 +479,8 @@ func ServersAzureADOnlyAuthentication_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(gens map[string]gopter.Gen) { gens["AzureADOnlyAuthentication"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAzureADOnlyAuthenticationOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_connection_policy_types_gen.go b/v2/api/sql/v1api20211101/servers_connection_policy_types_gen.go index 39246e167b3..2318b5f2b81 100644 --- a/v2/api/sql/v1api20211101/servers_connection_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_connection_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ServersConnectionPolicy) Default() { // defaultImpl applies the code generated defaults to the ServersConnectionPolicy resource func (policy *ServersConnectionPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ServersConnectionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersConnectionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersConnectionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersConnectionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersConnectionPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (policy *ServersConnectionPolicy) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (policy *ServersConnectionPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,9 +242,23 @@ func (policy *ServersConnectionPolicy) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ServersConnectionPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *ServersConnectionPolicy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -236,6 +273,14 @@ func (policy *ServersConnectionPolicy) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ServersConnectionPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ServersConnectionPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersConnectionPolicy) @@ -322,6 +367,10 @@ type ServersConnectionPolicy_Spec struct { // ConnectionType: The server connection type. ConnectionType *ServerConnectionPolicyProperties_ConnectionType `json:"connectionType,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersConnectionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -377,6 +426,8 @@ func (policy *ServersConnectionPolicy_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -449,6 +500,18 @@ func (policy *ServersConnectionPolicy_Spec) AssignProperties_From_ServersConnect policy.ConnectionType = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersConnectionPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ServersConnectionPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersConnectionPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -474,6 +537,18 @@ func (policy *ServersConnectionPolicy_Spec) AssignProperties_To_ServersConnectio destination.ConnectionType = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ServersConnectionPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ServersConnectionPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersConnectionPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -757,6 +832,110 @@ var serverConnectionPolicyProperties_ConnectionType_STATUS_Values = map[string]S "redirect": ServerConnectionPolicyProperties_ConnectionType_STATUS_Redirect, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersConnectionPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersConnectionPolicyOperatorSpec populates our ServersConnectionPolicyOperatorSpec from the provided source ServersConnectionPolicyOperatorSpec +func (operator *ServersConnectionPolicyOperatorSpec) AssignProperties_From_ServersConnectionPolicyOperatorSpec(source *storage.ServersConnectionPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersConnectionPolicyOperatorSpec populates the provided destination ServersConnectionPolicyOperatorSpec from our ServersConnectionPolicyOperatorSpec +func (operator *ServersConnectionPolicyOperatorSpec) AssignProperties_To_ServersConnectionPolicyOperatorSpec(destination *storage.ServersConnectionPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersConnectionPolicy{}, &ServersConnectionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/servers_connection_policy_types_gen_test.go b/v2/api/sql/v1api20211101/servers_connection_policy_types_gen_test.go index f1fc21cfe04..2403b34668d 100644 --- a/v2/api/sql/v1api20211101/servers_connection_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_connection_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersConnectionPolicy(gens map[string]gopt gens["Status"] = ServersConnectionPolicy_STATUSGenerator() } +func Test_ServersConnectionPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersConnectionPolicyOperatorSpec to ServersConnectionPolicyOperatorSpec via AssignProperties_To_ServersConnectionPolicyOperatorSpec & AssignProperties_From_ServersConnectionPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersConnectionPolicyOperatorSpec, ServersConnectionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersConnectionPolicyOperatorSpec tests if a specific instance of ServersConnectionPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersConnectionPolicyOperatorSpec(subject ServersConnectionPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersConnectionPolicyOperatorSpec + err := copied.AssignProperties_To_ServersConnectionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersConnectionPolicyOperatorSpec + err = actual.AssignProperties_From_ServersConnectionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersConnectionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersConnectionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersConnectionPolicyOperatorSpec, ServersConnectionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersConnectionPolicyOperatorSpec runs a test to see if a specific instance of ServersConnectionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersConnectionPolicyOperatorSpec(subject ServersConnectionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersConnectionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersConnectionPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersConnectionPolicyOperatorSpecGenerator() +var serversConnectionPolicyOperatorSpecGenerator gopter.Gen + +// ServersConnectionPolicyOperatorSpecGenerator returns a generator of ServersConnectionPolicyOperatorSpec instances for property testing. +func ServersConnectionPolicyOperatorSpecGenerator() gopter.Gen { + if serversConnectionPolicyOperatorSpecGenerator != nil { + return serversConnectionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversConnectionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicyOperatorSpec{}), generators) + + return serversConnectionPolicyOperatorSpecGenerator +} + func Test_ServersConnectionPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -359,6 +456,9 @@ func RunJSONSerializationTestForServersConnectionPolicy_Spec(subject ServersConn var serversConnectionPolicy_SpecGenerator gopter.Gen // ServersConnectionPolicy_SpecGenerator returns a generator of ServersConnectionPolicy_Spec instances for property testing. +// We first initialize serversConnectionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersConnectionPolicy_SpecGenerator() gopter.Gen { if serversConnectionPolicy_SpecGenerator != nil { return serversConnectionPolicy_SpecGenerator @@ -368,6 +468,12 @@ func ServersConnectionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(generators) serversConnectionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec(generators) + serversConnectionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicy_Spec{}), generators) + return serversConnectionPolicy_SpecGenerator } @@ -375,3 +481,8 @@ func ServersConnectionPolicy_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(gens map[string]gopter.Gen) { gens["ConnectionType"] = gen.PtrOf(gen.OneConstOf(ServerConnectionPolicyProperties_ConnectionType_Default, ServerConnectionPolicyProperties_ConnectionType_Proxy, ServerConnectionPolicyProperties_ConnectionType_Redirect)) } + +// AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersConnectionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_database_types_gen.go b/v2/api/sql/v1api20211101/servers_database_types_gen.go index 6fd8e7f93eb..f1e1cc06a09 100644 --- a/v2/api/sql/v1api20211101/servers_database_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_database_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (database *ServersDatabase) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersDatabase resource func (database *ServersDatabase) defaultImpl() { database.defaultAzureName() } +var _ configmaps.Exporter = &ServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *ServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *ServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabase{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (database *ServersDatabase) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (database *ServersDatabase) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference} + return []func() (admission.Warnings, error){database.validateResourceReferences, database.validateOwnerReference, database.validateSecretDestinations, database.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (database *ServersDatabase) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return database.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return database.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (database *ServersDatabase) validateConfigMapDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(database, nil, database.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (database *ServersDatabase) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (database *ServersDatabase) validateSecretDestinations() (admission.Warnings, error) { + if database.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(database, nil, database.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (database *ServersDatabase) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabase) @@ -399,6 +444,10 @@ type ServersDatabase_Spec struct { // MinCapacity: Minimal capacity that database will always have allocated, if not paused MinCapacity *float64 `json:"minCapacity,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -837,6 +886,8 @@ func (database *ServersDatabase_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": database.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1100,6 +1151,18 @@ func (database *ServersDatabase_Spec) AssignProperties_From_ServersDatabase_Spec database.MinCapacity = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabaseOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabaseOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + database.OperatorSpec = &operatorSpec + } else { + database.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1319,6 +1382,18 @@ func (database *ServersDatabase_Spec) AssignProperties_To_ServersDatabase_Spec(d destination.MinCapacity = nil } + // OperatorSpec + if database.OperatorSpec != nil { + var operatorSpec storage.ServersDatabaseOperatorSpec + err := database.OperatorSpec.AssignProperties_To_ServersDatabaseOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabaseOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = database.OriginalVersion() @@ -3488,6 +3563,110 @@ var databaseProperties_Status_STATUS_Values = map[string]DatabaseProperties_Stat "suspect": DatabaseProperties_Status_STATUS_Suspect, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabaseOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabaseOperatorSpec populates our ServersDatabaseOperatorSpec from the provided source ServersDatabaseOperatorSpec +func (operator *ServersDatabaseOperatorSpec) AssignProperties_From_ServersDatabaseOperatorSpec(source *storage.ServersDatabaseOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabaseOperatorSpec populates the provided destination ServersDatabaseOperatorSpec from our ServersDatabaseOperatorSpec +func (operator *ServersDatabaseOperatorSpec) AssignProperties_To_ServersDatabaseOperatorSpec(destination *storage.ServersDatabaseOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An ARM Resource SKU. type Sku struct { // Capacity: Capacity of the particular SKU. diff --git a/v2/api/sql/v1api20211101/servers_database_types_gen_test.go b/v2/api/sql/v1api20211101/servers_database_types_gen_test.go index f8df602575e..229b38c66d5 100644 --- a/v2/api/sql/v1api20211101/servers_database_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_database_types_gen_test.go @@ -504,6 +504,103 @@ func AddRelatedPropertyGeneratorsForServersDatabase(gens map[string]gopter.Gen) gens["Status"] = ServersDatabase_STATUSGenerator() } +func Test_ServersDatabaseOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabaseOperatorSpec to ServersDatabaseOperatorSpec via AssignProperties_To_ServersDatabaseOperatorSpec & AssignProperties_From_ServersDatabaseOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabaseOperatorSpec, ServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabaseOperatorSpec tests if a specific instance of ServersDatabaseOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabaseOperatorSpec(subject ServersDatabaseOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabaseOperatorSpec + err := copied.AssignProperties_To_ServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabaseOperatorSpec + err = actual.AssignProperties_From_ServersDatabaseOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabaseOperatorSpec, ServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabaseOperatorSpec runs a test to see if a specific instance of ServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabaseOperatorSpec(subject ServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabaseOperatorSpecGenerator() +var serversDatabaseOperatorSpecGenerator gopter.Gen + +// ServersDatabaseOperatorSpecGenerator returns a generator of ServersDatabaseOperatorSpec instances for property testing. +func ServersDatabaseOperatorSpecGenerator() gopter.Gen { + if serversDatabaseOperatorSpecGenerator != nil { + return serversDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabaseOperatorSpec{}), generators) + + return serversDatabaseOperatorSpecGenerator +} + func Test_ServersDatabase_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -862,6 +959,7 @@ func AddIndependentPropertyGeneratorsForServersDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForServersDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersDatabase_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(DatabaseIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServersDatabaseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen.go index aaad4f2a273..2345fa74368 100644 --- a/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesAdvancedThreatProtectionSetting resource func (setting *ServersDatabasesAdvancedThreatProtectionSetting) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesAdvancedThreatProtectionSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesAdvancedThreatProtectionSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesAdvancedThreatProtectionSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting) ValidateUpdate(o // createValidations validates the creation of the resource func (setting *ServersDatabasesAdvancedThreatProtectionSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting) updateValidation func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting) validateResource return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *ServersDatabasesAdvancedThreatProtectionSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesAdvancedThreatProtectionSetting) @@ -318,6 +363,10 @@ type ServersDatabasesAdvancedThreatProtectionSettingList struct { } type ServersDatabasesAdvancedThreatProtectionSetting_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -367,6 +416,8 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting_Spec) PopulateFro return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.ServersDatabasesAdvancedThreatProtectionSetting_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -441,6 +492,18 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting_Spec) ConvertSpec // AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSetting_Spec populates our ServersDatabasesAdvancedThreatProtectionSetting_Spec from the provided source ServersDatabasesAdvancedThreatProtectionSetting_Spec func (setting *ServersDatabasesAdvancedThreatProtectionSetting_Spec) AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSetting_Spec(source *storage.ServersDatabasesAdvancedThreatProtectionSetting_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -467,6 +530,18 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting_Spec) AssignPrope // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -754,6 +829,110 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) AssignPro return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec populates our ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec from the provided source ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec +func (operator *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(source *storage.ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec populates the provided destination ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec from our ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec +func (operator *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(destination *storage.ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersDatabasesAdvancedThreatProtectionSetting{}, &ServersDatabasesAdvancedThreatProtectionSettingList{}) } diff --git a/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen_test.go index 6c1b3e52d05..701495be400 100644 --- a/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_advanced_threat_protection_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSett gens["Status"] = ServersDatabasesAdvancedThreatProtectionSetting_STATUSGenerator() } +func Test_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec to ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec via AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec & AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec, ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec tests if a specific instance of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(subject ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec, ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec runs a test to see if a specific instance of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(subject ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator() +var serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator gopter.Gen + +// ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator returns a generator of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec instances for property testing. +func ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator() gopter.Gen { + if serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator != nil { + return serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec{}), generators) + + return serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator +} + func Test_ServersDatabasesAdvancedThreatProtectionSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -372,6 +469,9 @@ func RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSetting_ var serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator gopter.Gen // ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator returns a generator of ServersDatabasesAdvancedThreatProtectionSetting_Spec instances for property testing. +// We first initialize serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { if serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator != nil { return serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator @@ -381,6 +481,12 @@ func ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) + serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSetting_Spec{}), generators) + return serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator } @@ -388,3 +494,8 @@ func ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen func AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(gens map[string]gopter.Gen) { gens["State"] = gen.PtrOf(gen.OneConstOf(AdvancedThreatProtectionProperties_State_Disabled, AdvancedThreatProtectionProperties_State_Enabled, AdvancedThreatProtectionProperties_State_New)) } + +// AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen.go index 480005e8521..4e4ba8e3cf2 100644 --- a/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (setting *ServersDatabasesAuditingSetting) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesAuditingSetting resource func (setting *ServersDatabasesAuditingSetting) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesAuditingSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersDatabasesAuditingSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesAuditingSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersDatabasesAuditingSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesAuditingSetting{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (setting *ServersDatabasesAuditingSetting) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (setting *ServersDatabasesAuditingSetting) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference} + return []func() (admission.Warnings, error){setting.validateResourceReferences, setting.validateOwnerReference, setting.validateSecretDestinations, setting.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (setting *ServersDatabasesAuditingSetting) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return setting.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return setting.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (setting *ServersDatabasesAuditingSetting) validateConfigMapDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (setting *ServersDatabasesAuditingSetting) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (setting *ServersDatabasesAuditingSetting) validateSecretDestinations() (admission.Warnings, error) { + if setting.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(setting, nil, setting.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (setting *ServersDatabasesAuditingSetting) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesAuditingSetting) @@ -394,6 +439,10 @@ type ServersDatabasesAuditingSetting_Spec struct { // IsStorageSecondaryKeyInUse: Specifies whether storageAccountAccessKey value is the storage's secondary key. IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesAuditingSettingOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -553,6 +602,8 @@ func (setting *ServersDatabasesAuditingSetting_Spec) PopulateFromARM(owner genru } } + // no assignment for property "OperatorSpec" + // Set property "Owner": setting.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -692,6 +743,18 @@ func (setting *ServersDatabasesAuditingSetting_Spec) AssignProperties_From_Serve setting.IsStorageSecondaryKeyInUse = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesAuditingSettingOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec() to populate field OperatorSpec") + } + setting.OperatorSpec = &operatorSpec + } else { + setting.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -770,6 +833,18 @@ func (setting *ServersDatabasesAuditingSetting_Spec) AssignProperties_To_Servers destination.IsStorageSecondaryKeyInUse = nil } + // OperatorSpec + if setting.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesAuditingSettingOperatorSpec + err := setting.OperatorSpec.AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = setting.OriginalVersion() @@ -1352,6 +1427,110 @@ var databaseBlobAuditingPolicyProperties_State_STATUS_Values = map[string]Databa "enabled": DatabaseBlobAuditingPolicyProperties_State_STATUS_Enabled, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesAuditingSettingOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec populates our ServersDatabasesAuditingSettingOperatorSpec from the provided source ServersDatabasesAuditingSettingOperatorSpec +func (operator *ServersDatabasesAuditingSettingOperatorSpec) AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec(source *storage.ServersDatabasesAuditingSettingOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec populates the provided destination ServersDatabasesAuditingSettingOperatorSpec from our ServersDatabasesAuditingSettingOperatorSpec +func (operator *ServersDatabasesAuditingSettingOperatorSpec) AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec(destination *storage.ServersDatabasesAuditingSettingOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersDatabasesAuditingSetting{}, &ServersDatabasesAuditingSettingList{}) } diff --git a/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen_test.go index bd33ecb20b6..e0c362bf9ab 100644 --- a/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_auditing_setting_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting(gens map[str gens["Status"] = ServersDatabasesAuditingSetting_STATUSGenerator() } +func Test_ServersDatabasesAuditingSettingOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesAuditingSettingOperatorSpec to ServersDatabasesAuditingSettingOperatorSpec via AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec & AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesAuditingSettingOperatorSpec, ServersDatabasesAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesAuditingSettingOperatorSpec tests if a specific instance of ServersDatabasesAuditingSettingOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesAuditingSettingOperatorSpec(subject ServersDatabasesAuditingSettingOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesAuditingSettingOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesAuditingSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesAuditingSettingOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesAuditingSettingOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesAuditingSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesAuditingSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec, ServersDatabasesAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec runs a test to see if a specific instance of ServersDatabasesAuditingSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec(subject ServersDatabasesAuditingSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesAuditingSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesAuditingSettingOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabasesAuditingSettingOperatorSpecGenerator() +var serversDatabasesAuditingSettingOperatorSpecGenerator gopter.Gen + +// ServersDatabasesAuditingSettingOperatorSpecGenerator returns a generator of ServersDatabasesAuditingSettingOperatorSpec instances for property testing. +func ServersDatabasesAuditingSettingOperatorSpecGenerator() gopter.Gen { + if serversDatabasesAuditingSettingOperatorSpecGenerator != nil { + return serversDatabasesAuditingSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesAuditingSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSettingOperatorSpec{}), generators) + + return serversDatabasesAuditingSettingOperatorSpecGenerator +} + func Test_ServersDatabasesAuditingSetting_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -366,6 +463,9 @@ func RunJSONSerializationTestForServersDatabasesAuditingSetting_Spec(subject Ser var serversDatabasesAuditingSetting_SpecGenerator gopter.Gen // ServersDatabasesAuditingSetting_SpecGenerator returns a generator of ServersDatabasesAuditingSetting_Spec instances for property testing. +// We first initialize serversDatabasesAuditingSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesAuditingSetting_SpecGenerator() gopter.Gen { if serversDatabasesAuditingSetting_SpecGenerator != nil { return serversDatabasesAuditingSetting_SpecGenerator @@ -375,6 +475,12 @@ func ServersDatabasesAuditingSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) serversDatabasesAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) + serversDatabasesAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSetting_Spec{}), generators) + return serversDatabasesAuditingSetting_SpecGenerator } @@ -390,3 +496,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(gen gens["StorageAccountSubscriptionId"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesAuditingSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen.go index 9a2eec22cb4..2777600a742 100644 --- a/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesBackupLongTermRetentionPolicy resource func (policy *ServersDatabasesBackupLongTermRetentionPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesBackupLongTermRetentionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesBackupLongTermRetentionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesBackupLongTermRetentionPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy) ValidateUpdate(old // createValidations validates the creation of the resource func (policy *ServersDatabasesBackupLongTermRetentionPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,9 +242,23 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy) updateValidations() func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *ServersDatabasesBackupLongTermRetentionPolicy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -236,6 +273,14 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy) validateResourceRef return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ServersDatabasesBackupLongTermRetentionPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesBackupLongTermRetentionPolicy) @@ -321,6 +366,10 @@ type ServersDatabasesBackupLongTermRetentionPolicy_Spec struct { // MonthlyRetention: The monthly retention policy for an LTR backup in an ISO 8601 format. MonthlyRetention *string `json:"monthlyRetention,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -396,6 +445,8 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy_Spec) PopulateFromAR } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -489,6 +540,18 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy_Spec) AssignProperti // MonthlyRetention policy.MonthlyRetention = genruntime.ClonePointerToString(source.MonthlyRetention) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -518,6 +581,18 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy_Spec) AssignProperti // MonthlyRetention destination.MonthlyRetention = genruntime.ClonePointerToString(policy.MonthlyRetention) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -794,6 +869,110 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) AssignProper return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec populates our ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec from the provided source ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec +func (operator *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(source *storage.ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec populates the provided destination ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec from our ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec +func (operator *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(destination *storage.ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersDatabasesBackupLongTermRetentionPolicy{}, &ServersDatabasesBackupLongTermRetentionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen_test.go index f6d48f3511e..41792d74fef 100644 --- a/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_backup_long_term_retention_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolic gens["Status"] = ServersDatabasesBackupLongTermRetentionPolicy_STATUSGenerator() } +func Test_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec to ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec via AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec & AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec, ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec tests if a specific instance of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec, ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator() +var serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator returns a generator of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec instances for property testing. +func ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator != nil { + return serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec{}), generators) + + return serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesBackupLongTermRetentionPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicy_Sp var serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator gopter.Gen // ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator returns a generator of ServersDatabasesBackupLongTermRetentionPolicy_Spec instances for property testing. +// We first initialize serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator() gopter.Gen { if serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator != nil { return serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator @@ -369,6 +469,12 @@ func ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) + serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicy_Spec{}), generators) + return serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionP gens["WeeklyRetention"] = gen.PtrOf(gen.AlphaString()) gens["YearlyRetention"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen.go index 064a93adf72..493876d156d 100644 --- a/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesBackupShortTermRetentionPolicy resource func (policy *ServersDatabasesBackupShortTermRetentionPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesBackupShortTermRetentionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesBackupShortTermRetentionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesBackupShortTermRetentionPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy) ValidateUpdate(old // createValidations validates the creation of the resource func (policy *ServersDatabasesBackupShortTermRetentionPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,9 +242,23 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy) updateValidations( func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (policy *ServersDatabasesBackupShortTermRetentionPolicy) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(policy) @@ -236,6 +273,14 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy) validateResourceRe return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ServersDatabasesBackupShortTermRetentionPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesBackupShortTermRetentionPolicy) @@ -322,6 +367,10 @@ type ServersDatabasesBackupShortTermRetentionPolicy_Spec struct { // differential backup will be supported. This is only applicable to live databases but not dropped databases. DiffBackupIntervalInHours *BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours `json:"diffBackupIntervalInHours,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -384,6 +433,8 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy_Spec) PopulateFromA } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -464,6 +515,18 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy_Spec) AssignPropert policy.DiffBackupIntervalInHours = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -492,6 +555,18 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy_Spec) AssignPropert destination.DiffBackupIntervalInHours = nil } + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -753,6 +828,110 @@ const ( BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours_STATUS_24 = BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours_STATUS(24) ) +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec populates our ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec from the provided source ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec +func (operator *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(source *storage.ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec populates the provided destination ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec from our ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec +func (operator *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(destination *storage.ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersDatabasesBackupShortTermRetentionPolicy{}, &ServersDatabasesBackupShortTermRetentionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen_test.go index ff78c7db7e8..da3afa1d3ba 100644 --- a/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_backup_short_term_retention_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPoli gens["Status"] = ServersDatabasesBackupShortTermRetentionPolicy_STATUSGenerator() } +func Test_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec to ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec via AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec & AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec, ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec tests if a specific instance of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec, ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator() +var serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator returns a generator of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec instances for property testing. +func ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator != nil { + return serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec{}), generators) + + return serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesBackupShortTermRetentionPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicy_S var serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator gopter.Gen // ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator returns a generator of ServersDatabasesBackupShortTermRetentionPolicy_Spec instances for property testing. +// We first initialize serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator() gopter.Gen { if serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator != nil { return serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator @@ -367,6 +467,12 @@ func ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) + serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicy_Spec{}), generators) + return serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator } @@ -375,3 +481,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetention gens["DiffBackupIntervalInHours"] = gen.PtrOf(gen.OneConstOf(BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours_12, BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours_24)) gens["RetentionDays"] = gen.PtrOf(gen.Int()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen.go index 3fffb613314..d0d6e9f06ce 100644 --- a/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ServersDatabasesSecurityAlertPolicy) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesSecurityAlertPolicy resource func (policy *ServersDatabasesSecurityAlertPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesSecurityAlertPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesSecurityAlertPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesSecurityAlertPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesSecurityAlertPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesSecurityAlertPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (policy *ServersDatabasesSecurityAlertPolicy) ValidateUpdate(old runtime.Ob // createValidations validates the creation of the resource func (policy *ServersDatabasesSecurityAlertPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (policy *ServersDatabasesSecurityAlertPolicy) updateValidations() []func(ol func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ServersDatabasesSecurityAlertPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (policy *ServersDatabasesSecurityAlertPolicy) validateResourceReferences() return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ServersDatabasesSecurityAlertPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ServersDatabasesSecurityAlertPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesSecurityAlertPolicy) @@ -328,6 +373,10 @@ type ServersDatabasesSecurityAlertPolicy_Spec struct { // EmailAddresses: Specifies an array of e-mail addresses to which the alert is sent. EmailAddresses []string `json:"emailAddresses,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesSecurityAlertPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -444,6 +493,8 @@ func (policy *ServersDatabasesSecurityAlertPolicy_Spec) PopulateFromARM(owner ge } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -552,6 +603,18 @@ func (policy *ServersDatabasesSecurityAlertPolicy_Spec) AssignProperties_From_Se // EmailAddresses policy.EmailAddresses = genruntime.CloneSliceOfString(source.EmailAddresses) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesSecurityAlertPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -606,6 +669,18 @@ func (policy *ServersDatabasesSecurityAlertPolicy_Spec) AssignProperties_To_Serv // EmailAddresses destination.EmailAddresses = genruntime.CloneSliceOfString(policy.EmailAddresses) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesSecurityAlertPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -1054,6 +1129,110 @@ var databaseSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_STATUS_Val "enabled": DatabaseSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_STATUS_Enabled, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesSecurityAlertPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec populates our ServersDatabasesSecurityAlertPolicyOperatorSpec from the provided source ServersDatabasesSecurityAlertPolicyOperatorSpec +func (operator *ServersDatabasesSecurityAlertPolicyOperatorSpec) AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec(source *storage.ServersDatabasesSecurityAlertPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec populates the provided destination ServersDatabasesSecurityAlertPolicyOperatorSpec from our ServersDatabasesSecurityAlertPolicyOperatorSpec +func (operator *ServersDatabasesSecurityAlertPolicyOperatorSpec) AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec(destination *storage.ServersDatabasesSecurityAlertPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersDatabasesSecurityAlertPolicy{}, &ServersDatabasesSecurityAlertPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen_test.go index 862ec287289..d3dd036d965 100644 --- a/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_security_alert_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy(gens map gens["Status"] = ServersDatabasesSecurityAlertPolicy_STATUSGenerator() } +func Test_ServersDatabasesSecurityAlertPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesSecurityAlertPolicyOperatorSpec to ServersDatabasesSecurityAlertPolicyOperatorSpec via AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec & AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesSecurityAlertPolicyOperatorSpec, ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesSecurityAlertPolicyOperatorSpec tests if a specific instance of ServersDatabasesSecurityAlertPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesSecurityAlertPolicyOperatorSpec(subject ServersDatabasesSecurityAlertPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesSecurityAlertPolicyOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesSecurityAlertPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesSecurityAlertPolicyOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesSecurityAlertPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesSecurityAlertPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesSecurityAlertPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec, ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesSecurityAlertPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec(subject ServersDatabasesSecurityAlertPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesSecurityAlertPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesSecurityAlertPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator() +var serversDatabasesSecurityAlertPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator returns a generator of ServersDatabasesSecurityAlertPolicyOperatorSpec instances for property testing. +func ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesSecurityAlertPolicyOperatorSpecGenerator != nil { + return serversDatabasesSecurityAlertPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesSecurityAlertPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicyOperatorSpec{}), generators) + + return serversDatabasesSecurityAlertPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesSecurityAlertPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -377,6 +474,9 @@ func RunJSONSerializationTestForServersDatabasesSecurityAlertPolicy_Spec(subject var serversDatabasesSecurityAlertPolicy_SpecGenerator gopter.Gen // ServersDatabasesSecurityAlertPolicy_SpecGenerator returns a generator of ServersDatabasesSecurityAlertPolicy_Spec instances for property testing. +// We first initialize serversDatabasesSecurityAlertPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesSecurityAlertPolicy_SpecGenerator() gopter.Gen { if serversDatabasesSecurityAlertPolicy_SpecGenerator != nil { return serversDatabasesSecurityAlertPolicy_SpecGenerator @@ -386,6 +486,12 @@ func ServersDatabasesSecurityAlertPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) serversDatabasesSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) + serversDatabasesSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicy_Spec{}), generators) + return serversDatabasesSecurityAlertPolicy_SpecGenerator } @@ -398,3 +504,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec gens["State"] = gen.PtrOf(gen.OneConstOf(DatabaseSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_Disabled, DatabaseSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_Enabled)) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen.go index e2cd781fdd6..f019eab96af 100644 --- a/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (encryption *ServersDatabasesTransparentDataEncryption) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesTransparentDataEncryption resource func (encryption *ServersDatabasesTransparentDataEncryption) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesTransparentDataEncryption{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryption *ServersDatabasesTransparentDataEncryption) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryption.Spec.OperatorSpec == nil { + return nil + } + return encryption.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesTransparentDataEncryption{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryption *ServersDatabasesTransparentDataEncryption) SecretDestinationExpressions() []*core.DestinationExpression { + if encryption.Spec.OperatorSpec == nil { + return nil + } + return encryption.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesTransparentDataEncryption{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (encryption *ServersDatabasesTransparentDataEncryption) ValidateUpdate(old // createValidations validates the creation of the resource func (encryption *ServersDatabasesTransparentDataEncryption) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){encryption.validateResourceReferences, encryption.validateOwnerReference} + return []func() (admission.Warnings, error){encryption.validateResourceReferences, encryption.validateOwnerReference, encryption.validateSecretDestinations, encryption.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,9 +242,23 @@ func (encryption *ServersDatabasesTransparentDataEncryption) updateValidations() func(old runtime.Object) (admission.Warnings, error) { return encryption.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return encryption.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return encryption.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (encryption *ServersDatabasesTransparentDataEncryption) validateConfigMapDestinations() (admission.Warnings, error) { + if encryption.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(encryption, nil, encryption.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (encryption *ServersDatabasesTransparentDataEncryption) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(encryption) @@ -236,6 +273,14 @@ func (encryption *ServersDatabasesTransparentDataEncryption) validateResourceRef return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (encryption *ServersDatabasesTransparentDataEncryption) validateSecretDestinations() (admission.Warnings, error) { + if encryption.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(encryption, nil, encryption.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (encryption *ServersDatabasesTransparentDataEncryption) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesTransparentDataEncryption) @@ -318,6 +363,10 @@ type ServersDatabasesTransparentDataEncryptionList struct { } type ServersDatabasesTransparentDataEncryption_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesTransparentDataEncryptionOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -366,6 +415,8 @@ func (encryption *ServersDatabasesTransparentDataEncryption_Spec) PopulateFromAR return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.ServersDatabasesTransparentDataEncryption_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": encryption.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -440,6 +491,18 @@ func (encryption *ServersDatabasesTransparentDataEncryption_Spec) ConvertSpecTo( // AssignProperties_From_ServersDatabasesTransparentDataEncryption_Spec populates our ServersDatabasesTransparentDataEncryption_Spec from the provided source ServersDatabasesTransparentDataEncryption_Spec func (encryption *ServersDatabasesTransparentDataEncryption_Spec) AssignProperties_From_ServersDatabasesTransparentDataEncryption_Spec(source *storage.ServersDatabasesTransparentDataEncryption_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesTransparentDataEncryptionOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec() to populate field OperatorSpec") + } + encryption.OperatorSpec = &operatorSpec + } else { + encryption.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -466,6 +529,18 @@ func (encryption *ServersDatabasesTransparentDataEncryption_Spec) AssignProperti // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if encryption.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesTransparentDataEncryptionOperatorSpec + err := encryption.OperatorSpec.AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = encryption.OriginalVersion() @@ -696,6 +771,110 @@ func (encryption *ServersDatabasesTransparentDataEncryption_STATUS) AssignProper return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesTransparentDataEncryptionOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec populates our ServersDatabasesTransparentDataEncryptionOperatorSpec from the provided source ServersDatabasesTransparentDataEncryptionOperatorSpec +func (operator *ServersDatabasesTransparentDataEncryptionOperatorSpec) AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec(source *storage.ServersDatabasesTransparentDataEncryptionOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec populates the provided destination ServersDatabasesTransparentDataEncryptionOperatorSpec from our ServersDatabasesTransparentDataEncryptionOperatorSpec +func (operator *ServersDatabasesTransparentDataEncryptionOperatorSpec) AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec(destination *storage.ServersDatabasesTransparentDataEncryptionOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Disabled","Enabled"} type TransparentDataEncryptionProperties_State string diff --git a/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen_test.go index 871ef4349af..85ed3429b26 100644 --- a/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_transparent_data_encryption_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption(ge gens["Status"] = ServersDatabasesTransparentDataEncryption_STATUSGenerator() } +func Test_ServersDatabasesTransparentDataEncryptionOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesTransparentDataEncryptionOperatorSpec to ServersDatabasesTransparentDataEncryptionOperatorSpec via AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec & AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesTransparentDataEncryptionOperatorSpec, ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesTransparentDataEncryptionOperatorSpec tests if a specific instance of ServersDatabasesTransparentDataEncryptionOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesTransparentDataEncryptionOperatorSpec(subject ServersDatabasesTransparentDataEncryptionOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesTransparentDataEncryptionOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesTransparentDataEncryptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesTransparentDataEncryptionOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesTransparentDataEncryptionOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesTransparentDataEncryptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesTransparentDataEncryptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec, ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec runs a test to see if a specific instance of ServersDatabasesTransparentDataEncryptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec(subject ServersDatabasesTransparentDataEncryptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesTransparentDataEncryptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesTransparentDataEncryptionOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator() +var serversDatabasesTransparentDataEncryptionOperatorSpecGenerator gopter.Gen + +// ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator returns a generator of ServersDatabasesTransparentDataEncryptionOperatorSpec instances for property testing. +func ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator() gopter.Gen { + if serversDatabasesTransparentDataEncryptionOperatorSpecGenerator != nil { + return serversDatabasesTransparentDataEncryptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesTransparentDataEncryptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryptionOperatorSpec{}), generators) + + return serversDatabasesTransparentDataEncryptionOperatorSpecGenerator +} + func Test_ServersDatabasesTransparentDataEncryption_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -357,6 +454,9 @@ func RunJSONSerializationTestForServersDatabasesTransparentDataEncryption_Spec(s var serversDatabasesTransparentDataEncryption_SpecGenerator gopter.Gen // ServersDatabasesTransparentDataEncryption_SpecGenerator returns a generator of ServersDatabasesTransparentDataEncryption_Spec instances for property testing. +// We first initialize serversDatabasesTransparentDataEncryption_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesTransparentDataEncryption_SpecGenerator() gopter.Gen { if serversDatabasesTransparentDataEncryption_SpecGenerator != nil { return serversDatabasesTransparentDataEncryption_SpecGenerator @@ -366,6 +466,12 @@ func ServersDatabasesTransparentDataEncryption_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) serversDatabasesTransparentDataEncryption_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryption_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) + serversDatabasesTransparentDataEncryption_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryption_Spec{}), generators) + return serversDatabasesTransparentDataEncryption_SpecGenerator } @@ -373,3 +479,8 @@ func ServersDatabasesTransparentDataEncryption_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(gens map[string]gopter.Gen) { gens["State"] = gen.PtrOf(gen.OneConstOf(TransparentDataEncryptionProperties_State_Disabled, TransparentDataEncryptionProperties_State_Enabled)) } + +// AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen.go b/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen.go index 9b746f2b5c5..799b631efc9 100644 --- a/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (assessment *ServersDatabasesVulnerabilityAssessment) Default() { // defaultImpl applies the code generated defaults to the ServersDatabasesVulnerabilityAssessment resource func (assessment *ServersDatabasesVulnerabilityAssessment) defaultImpl() {} +var _ configmaps.Exporter = &ServersDatabasesVulnerabilityAssessment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assessment *ServersDatabasesVulnerabilityAssessment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesVulnerabilityAssessment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assessment *ServersDatabasesVulnerabilityAssessment) SecretDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersDatabasesVulnerabilityAssessment{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +225,7 @@ func (assessment *ServersDatabasesVulnerabilityAssessment) ValidateUpdate(old ru // createValidations validates the creation of the resource func (assessment *ServersDatabasesVulnerabilityAssessment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assessment.validateResourceReferences, assessment.validateOwnerReference, assessment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assessment.validateResourceReferences, assessment.validateOwnerReference, assessment.validateSecretDestinations, assessment.validateConfigMapDestinations, assessment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -221,12 +243,26 @@ func (assessment *ServersDatabasesVulnerabilityAssessment) updateValidations() [ func(old runtime.Object) (admission.Warnings, error) { return assessment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return assessment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assessment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assessment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assessment *ServersDatabasesVulnerabilityAssessment) validateConfigMapDestinations() (admission.Warnings, error) { + if assessment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assessment, nil, assessment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assessment *ServersDatabasesVulnerabilityAssessment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assessment.Spec) @@ -250,6 +286,14 @@ func (assessment *ServersDatabasesVulnerabilityAssessment) validateResourceRefer return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assessment *ServersDatabasesVulnerabilityAssessment) validateSecretDestinations() (admission.Warnings, error) { + if assessment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assessment, nil, assessment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assessment *ServersDatabasesVulnerabilityAssessment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersDatabasesVulnerabilityAssessment) @@ -332,6 +376,10 @@ type ServersDatabasesVulnerabilityAssessmentList struct { } type ServersDatabasesVulnerabilityAssessment_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersDatabasesVulnerabilityAssessmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -433,6 +481,8 @@ func (assessment *ServersDatabasesVulnerabilityAssessment_Spec) PopulateFromARM( return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.ServersDatabasesVulnerabilityAssessment_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": assessment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -525,6 +575,18 @@ func (assessment *ServersDatabasesVulnerabilityAssessment_Spec) ConvertSpecTo(de // AssignProperties_From_ServersDatabasesVulnerabilityAssessment_Spec populates our ServersDatabasesVulnerabilityAssessment_Spec from the provided source ServersDatabasesVulnerabilityAssessment_Spec func (assessment *ServersDatabasesVulnerabilityAssessment_Spec) AssignProperties_From_ServersDatabasesVulnerabilityAssessment_Spec(source *storage.ServersDatabasesVulnerabilityAssessment_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersDatabasesVulnerabilityAssessmentOperatorSpec + err := operatorSpec.AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec() to populate field OperatorSpec") + } + assessment.OperatorSpec = &operatorSpec + } else { + assessment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -581,6 +643,18 @@ func (assessment *ServersDatabasesVulnerabilityAssessment_Spec) AssignProperties // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if assessment.OperatorSpec != nil { + var operatorSpec storage.ServersDatabasesVulnerabilityAssessmentOperatorSpec + err := assessment.OperatorSpec.AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = assessment.OriginalVersion() @@ -879,6 +953,110 @@ func (assessment *ServersDatabasesVulnerabilityAssessment_STATUS) AssignProperti return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesVulnerabilityAssessmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec populates our ServersDatabasesVulnerabilityAssessmentOperatorSpec from the provided source ServersDatabasesVulnerabilityAssessmentOperatorSpec +func (operator *ServersDatabasesVulnerabilityAssessmentOperatorSpec) AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec(source *storage.ServersDatabasesVulnerabilityAssessmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec populates the provided destination ServersDatabasesVulnerabilityAssessmentOperatorSpec from our ServersDatabasesVulnerabilityAssessmentOperatorSpec +func (operator *ServersDatabasesVulnerabilityAssessmentOperatorSpec) AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec(destination *storage.ServersDatabasesVulnerabilityAssessmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Properties of a Vulnerability Assessment recurring scans. type VulnerabilityAssessmentRecurringScansProperties struct { // EmailSubscriptionAdmins: Specifies that the schedule scan notification will be is sent to the subscription diff --git a/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen_test.go b/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen_test.go index 895fbc13993..73f9ed68012 100644 --- a/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_databases_vulnerability_assessment_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment(gens gens["Status"] = ServersDatabasesVulnerabilityAssessment_STATUSGenerator() } +func Test_ServersDatabasesVulnerabilityAssessmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersDatabasesVulnerabilityAssessmentOperatorSpec to ServersDatabasesVulnerabilityAssessmentOperatorSpec via AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec & AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersDatabasesVulnerabilityAssessmentOperatorSpec, ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersDatabasesVulnerabilityAssessmentOperatorSpec tests if a specific instance of ServersDatabasesVulnerabilityAssessmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersDatabasesVulnerabilityAssessmentOperatorSpec(subject ServersDatabasesVulnerabilityAssessmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersDatabasesVulnerabilityAssessmentOperatorSpec + err := copied.AssignProperties_To_ServersDatabasesVulnerabilityAssessmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersDatabasesVulnerabilityAssessmentOperatorSpec + err = actual.AssignProperties_From_ServersDatabasesVulnerabilityAssessmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersDatabasesVulnerabilityAssessmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesVulnerabilityAssessmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec, ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec runs a test to see if a specific instance of ServersDatabasesVulnerabilityAssessmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec(subject ServersDatabasesVulnerabilityAssessmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesVulnerabilityAssessmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesVulnerabilityAssessmentOperatorSpec instances for property testing - lazily instantiated +// by ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator() +var serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator gopter.Gen + +// ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator returns a generator of ServersDatabasesVulnerabilityAssessmentOperatorSpec instances for property testing. +func ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator() gopter.Gen { + if serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator != nil { + return serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesVulnerabilityAssessmentOperatorSpec{}), generators) + + return serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator +} + func Test_ServersDatabasesVulnerabilityAssessment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,6 +496,7 @@ func AddIndependentPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_ // AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator()) gens["RecurringScans"] = gen.PtrOf(VulnerabilityAssessmentRecurringScansPropertiesGenerator()) } diff --git a/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen.go b/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen.go index d7852d1f1bf..63ba1d1998a 100644 --- a/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (pool *ServersElasticPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersElasticPool resource func (pool *ServersElasticPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &ServersElasticPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ServersElasticPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersElasticPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ServersElasticPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersElasticPool{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (pool *ServersElasticPool) ValidateUpdate(old runtime.Object) (admission.Wa // createValidations validates the creation of the resource func (pool *ServersElasticPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (pool *ServersElasticPool) updateValidations() []func(old runtime.Object) ( func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *ServersElasticPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (pool *ServersElasticPool) validateResourceReferences() (admission.Warnings return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *ServersElasticPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *ServersElasticPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersElasticPool) @@ -351,6 +396,10 @@ type ServersElasticPool_Spec struct { // MinCapacity: Minimal capacity that serverless pool will not shrink below, if not paused MinCapacity *float64 `json:"minCapacity,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersElasticPoolOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -528,6 +577,8 @@ func (pool *ServersElasticPool_Spec) PopulateFromARM(owner genruntime.ArbitraryO } } + // no assignment for property "OperatorSpec" + // Set property "Owner": pool.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -665,6 +716,18 @@ func (pool *ServersElasticPool_Spec) AssignProperties_From_ServersElasticPool_Sp pool.MinCapacity = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersElasticPoolOperatorSpec + err := operatorSpec.AssignProperties_From_ServersElasticPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersElasticPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -748,6 +811,18 @@ func (pool *ServersElasticPool_Spec) AssignProperties_To_ServersElasticPool_Spec destination.MinCapacity = nil } + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.ServersElasticPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_ServersElasticPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersElasticPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = pool.OriginalVersion() @@ -1631,6 +1706,110 @@ var elasticPoolProperties_State_STATUS_Values = map[string]ElasticPoolProperties "ready": ElasticPoolProperties_State_STATUS_Ready, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersElasticPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersElasticPoolOperatorSpec populates our ServersElasticPoolOperatorSpec from the provided source ServersElasticPoolOperatorSpec +func (operator *ServersElasticPoolOperatorSpec) AssignProperties_From_ServersElasticPoolOperatorSpec(source *storage.ServersElasticPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersElasticPoolOperatorSpec populates the provided destination ServersElasticPoolOperatorSpec from our ServersElasticPoolOperatorSpec +func (operator *ServersElasticPoolOperatorSpec) AssignProperties_To_ServersElasticPoolOperatorSpec(destination *storage.ServersElasticPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersElasticPool{}, &ServersElasticPoolList{}) } diff --git a/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen_test.go b/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen_test.go index 923852c4ab0..209bee02031 100644 --- a/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_elastic_pool_types_gen_test.go @@ -372,6 +372,103 @@ func AddRelatedPropertyGeneratorsForServersElasticPool(gens map[string]gopter.Ge gens["Status"] = ServersElasticPool_STATUSGenerator() } +func Test_ServersElasticPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersElasticPoolOperatorSpec to ServersElasticPoolOperatorSpec via AssignProperties_To_ServersElasticPoolOperatorSpec & AssignProperties_From_ServersElasticPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersElasticPoolOperatorSpec, ServersElasticPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersElasticPoolOperatorSpec tests if a specific instance of ServersElasticPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersElasticPoolOperatorSpec(subject ServersElasticPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersElasticPoolOperatorSpec + err := copied.AssignProperties_To_ServersElasticPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersElasticPoolOperatorSpec + err = actual.AssignProperties_From_ServersElasticPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersElasticPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersElasticPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersElasticPoolOperatorSpec, ServersElasticPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersElasticPoolOperatorSpec runs a test to see if a specific instance of ServersElasticPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersElasticPoolOperatorSpec(subject ServersElasticPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersElasticPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersElasticPoolOperatorSpec instances for property testing - lazily instantiated by +// ServersElasticPoolOperatorSpecGenerator() +var serversElasticPoolOperatorSpecGenerator gopter.Gen + +// ServersElasticPoolOperatorSpecGenerator returns a generator of ServersElasticPoolOperatorSpec instances for property testing. +func ServersElasticPoolOperatorSpecGenerator() gopter.Gen { + if serversElasticPoolOperatorSpecGenerator != nil { + return serversElasticPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversElasticPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersElasticPoolOperatorSpec{}), generators) + + return serversElasticPoolOperatorSpecGenerator +} + func Test_ServersElasticPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -629,6 +726,7 @@ func AddIndependentPropertyGeneratorsForServersElasticPool_Spec(gens map[string] // AddRelatedPropertyGeneratorsForServersElasticPool_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersElasticPool_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersElasticPoolOperatorSpecGenerator()) gens["PerDatabaseSettings"] = gen.PtrOf(ElasticPoolPerDatabaseSettingsGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/sql/v1api20211101/servers_failover_group_types_gen.go b/v2/api/sql/v1api20211101/servers_failover_group_types_gen.go index e5a9e0d3bc7..89c4c51cd87 100644 --- a/v2/api/sql/v1api20211101/servers_failover_group_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_failover_group_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (group *ServersFailoverGroup) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersFailoverGroup resource func (group *ServersFailoverGroup) defaultImpl() { group.defaultAzureName() } +var _ configmaps.Exporter = &ServersFailoverGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ServersFailoverGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersFailoverGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ServersFailoverGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersFailoverGroup{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (group *ServersFailoverGroup) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (group *ServersFailoverGroup) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference} + return []func() (admission.Warnings, error){group.validateResourceReferences, group.validateOwnerReference, group.validateSecretDestinations, group.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (group *ServersFailoverGroup) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return group.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return group.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (group *ServersFailoverGroup) validateConfigMapDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(group, nil, group.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (group *ServersFailoverGroup) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (group *ServersFailoverGroup) validateSecretDestinations() (admission.Warnings, error) { + if group.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(group, nil, group.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (group *ServersFailoverGroup) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersFailoverGroup) @@ -333,6 +378,10 @@ type ServersFailoverGroup_Spec struct { // DatabasesReferences: List of databases in the failover group. DatabasesReferences []genruntime.ResourceReference `armReference:"Databases" json:"databasesReferences,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersFailoverGroupOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -431,6 +480,8 @@ func (group *ServersFailoverGroup_Spec) PopulateFromARM(owner genruntime.Arbitra // no assignment for property "DatabasesReferences" + // no assignment for property "OperatorSpec" + // Set property "Owner": group.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -559,6 +610,18 @@ func (group *ServersFailoverGroup_Spec) AssignProperties_From_ServersFailoverGro group.DatabasesReferences = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersFailoverGroupOperatorSpec + err := operatorSpec.AssignProperties_From_ServersFailoverGroupOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersFailoverGroupOperatorSpec() to populate field OperatorSpec") + } + group.OperatorSpec = &operatorSpec + } else { + group.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -637,6 +700,18 @@ func (group *ServersFailoverGroup_Spec) AssignProperties_To_ServersFailoverGroup destination.DatabasesReferences = nil } + // OperatorSpec + if group.OperatorSpec != nil { + var operatorSpec storage.ServersFailoverGroupOperatorSpec + err := group.OperatorSpec.AssignProperties_To_ServersFailoverGroupOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersFailoverGroupOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = group.OriginalVersion() @@ -1756,6 +1831,110 @@ func (info *PartnerInfo_STATUS) AssignProperties_To_PartnerInfo_STATUS(destinati return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersFailoverGroupOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersFailoverGroupOperatorSpec populates our ServersFailoverGroupOperatorSpec from the provided source ServersFailoverGroupOperatorSpec +func (operator *ServersFailoverGroupOperatorSpec) AssignProperties_From_ServersFailoverGroupOperatorSpec(source *storage.ServersFailoverGroupOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersFailoverGroupOperatorSpec populates the provided destination ServersFailoverGroupOperatorSpec from our ServersFailoverGroupOperatorSpec +func (operator *ServersFailoverGroupOperatorSpec) AssignProperties_To_ServersFailoverGroupOperatorSpec(destination *storage.ServersFailoverGroupOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Disabled","Enabled"} type FailoverGroupReadOnlyEndpoint_FailoverPolicy string diff --git a/v2/api/sql/v1api20211101/servers_failover_group_types_gen_test.go b/v2/api/sql/v1api20211101/servers_failover_group_types_gen_test.go index ceb6730be0a..bdd9f896742 100644 --- a/v2/api/sql/v1api20211101/servers_failover_group_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_failover_group_types_gen_test.go @@ -779,6 +779,103 @@ func AddRelatedPropertyGeneratorsForServersFailoverGroup(gens map[string]gopter. gens["Status"] = ServersFailoverGroup_STATUSGenerator() } +func Test_ServersFailoverGroupOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersFailoverGroupOperatorSpec to ServersFailoverGroupOperatorSpec via AssignProperties_To_ServersFailoverGroupOperatorSpec & AssignProperties_From_ServersFailoverGroupOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersFailoverGroupOperatorSpec, ServersFailoverGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersFailoverGroupOperatorSpec tests if a specific instance of ServersFailoverGroupOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersFailoverGroupOperatorSpec(subject ServersFailoverGroupOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersFailoverGroupOperatorSpec + err := copied.AssignProperties_To_ServersFailoverGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersFailoverGroupOperatorSpec + err = actual.AssignProperties_From_ServersFailoverGroupOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersFailoverGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersFailoverGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersFailoverGroupOperatorSpec, ServersFailoverGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersFailoverGroupOperatorSpec runs a test to see if a specific instance of ServersFailoverGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersFailoverGroupOperatorSpec(subject ServersFailoverGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersFailoverGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersFailoverGroupOperatorSpec instances for property testing - lazily instantiated by +// ServersFailoverGroupOperatorSpecGenerator() +var serversFailoverGroupOperatorSpecGenerator gopter.Gen + +// ServersFailoverGroupOperatorSpecGenerator returns a generator of ServersFailoverGroupOperatorSpec instances for property testing. +func ServersFailoverGroupOperatorSpecGenerator() gopter.Gen { + if serversFailoverGroupOperatorSpecGenerator != nil { + return serversFailoverGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversFailoverGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersFailoverGroupOperatorSpec{}), generators) + + return serversFailoverGroupOperatorSpecGenerator +} + func Test_ServersFailoverGroup_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1024,6 +1121,7 @@ func AddIndependentPropertyGeneratorsForServersFailoverGroup_Spec(gens map[strin // AddRelatedPropertyGeneratorsForServersFailoverGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersFailoverGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersFailoverGroupOperatorSpecGenerator()) gens["PartnerServers"] = gen.SliceOf(PartnerInfoGenerator()) gens["ReadOnlyEndpoint"] = gen.PtrOf(FailoverGroupReadOnlyEndpointGenerator()) gens["ReadWriteEndpoint"] = gen.PtrOf(FailoverGroupReadWriteEndpointGenerator()) diff --git a/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen.go index 29027f2fe1e..e97c0fbe30d 100644 --- a/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *ServersFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersFirewallRule resource func (rule *ServersFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &ServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersFirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *ServersFirewallRule) ValidateUpdate(old runtime.Object) (admission.W // createValidations validates the creation of the resource func (rule *ServersFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (rule *ServersFirewallRule) updateValidations() []func(old runtime.Object) func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *ServersFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *ServersFirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -244,6 +281,14 @@ func (rule *ServersFirewallRule) validateResourceReferences() (admission.Warning return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *ServersFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *ServersFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersFirewallRule) @@ -334,6 +379,10 @@ type ServersFirewallRule_Spec struct { // startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. EndIpAddress *string `json:"endIpAddress,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -396,6 +445,8 @@ func (rule *ServersFirewallRule_Spec) PopulateFromARM(owner genruntime.Arbitrary } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -474,6 +525,18 @@ func (rule *ServersFirewallRule_Spec) AssignProperties_From_ServersFirewallRule_ // EndIpAddress rule.EndIpAddress = genruntime.ClonePointerToString(source.EndIpAddress) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_ServersFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -500,6 +563,18 @@ func (rule *ServersFirewallRule_Spec) AssignProperties_To_ServersFirewallRule_Sp // EndIpAddress destination.EndIpAddress = genruntime.ClonePointerToString(rule.EndIpAddress) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.ServersFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_ServersFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -733,6 +808,110 @@ func (rule *ServersFirewallRule_STATUS) AssignProperties_To_ServersFirewallRule_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersFirewallRuleOperatorSpec populates our ServersFirewallRuleOperatorSpec from the provided source ServersFirewallRuleOperatorSpec +func (operator *ServersFirewallRuleOperatorSpec) AssignProperties_From_ServersFirewallRuleOperatorSpec(source *storage.ServersFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersFirewallRuleOperatorSpec populates the provided destination ServersFirewallRuleOperatorSpec from our ServersFirewallRuleOperatorSpec +func (operator *ServersFirewallRuleOperatorSpec) AssignProperties_To_ServersFirewallRuleOperatorSpec(destination *storage.ServersFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersFirewallRule{}, &ServersFirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen_test.go index fb96ccf457a..7488ef8bab8 100644 --- a/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersFirewallRule(gens map[string]gopter.G gens["Status"] = ServersFirewallRule_STATUSGenerator() } +func Test_ServersFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersFirewallRuleOperatorSpec to ServersFirewallRuleOperatorSpec via AssignProperties_To_ServersFirewallRuleOperatorSpec & AssignProperties_From_ServersFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersFirewallRuleOperatorSpec, ServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersFirewallRuleOperatorSpec tests if a specific instance of ServersFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersFirewallRuleOperatorSpec(subject ServersFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersFirewallRuleOperatorSpec + err := copied.AssignProperties_To_ServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersFirewallRuleOperatorSpec + err = actual.AssignProperties_From_ServersFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersFirewallRuleOperatorSpec, ServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersFirewallRuleOperatorSpec runs a test to see if a specific instance of ServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersFirewallRuleOperatorSpec(subject ServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersFirewallRuleOperatorSpecGenerator() +var serversFirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersFirewallRuleOperatorSpecGenerator returns a generator of ServersFirewallRuleOperatorSpec instances for property testing. +func ServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversFirewallRuleOperatorSpecGenerator != nil { + return serversFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRuleOperatorSpec{}), generators) + + return serversFirewallRuleOperatorSpecGenerator +} + func Test_ServersFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForServersFirewallRule_Spec(subject ServersFirewall var serversFirewallRule_SpecGenerator gopter.Gen // ServersFirewallRule_SpecGenerator returns a generator of ServersFirewallRule_Spec instances for property testing. +// We first initialize serversFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersFirewallRule_SpecGenerator() gopter.Gen { if serversFirewallRule_SpecGenerator != nil { return serversFirewallRule_SpecGenerator @@ -367,6 +467,12 @@ func ServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(generators) serversFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersFirewallRule_Spec(generators) + serversFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRule_Spec{}), generators) + return serversFirewallRule_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(gens map[string gens["EndIpAddress"] = gen.PtrOf(gen.AlphaString()) gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen.go index e117311bfaf..b565a9eb67c 100644 --- a/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *ServersIPV6FirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersIPV6FirewallRule resource func (rule *ServersIPV6FirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &ServersIPV6FirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersIPV6FirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersIPV6FirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersIPV6FirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersIPV6FirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *ServersIPV6FirewallRule) ValidateUpdate(old runtime.Object) (admissi // createValidations validates the creation of the resource func (rule *ServersIPV6FirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (rule *ServersIPV6FirewallRule) updateValidations() []func(old runtime.Obje func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *ServersIPV6FirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *ServersIPV6FirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -244,6 +281,14 @@ func (rule *ServersIPV6FirewallRule) validateResourceReferences() (admission.War return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *ServersIPV6FirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *ServersIPV6FirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersIPV6FirewallRule) @@ -334,6 +379,10 @@ type ServersIPV6FirewallRule_Spec struct { // startIpAddress. EndIPv6Address *string `json:"endIPv6Address,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersIPV6FirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -395,6 +444,8 @@ func (rule *ServersIPV6FirewallRule_Spec) PopulateFromARM(owner genruntime.Arbit } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -473,6 +524,18 @@ func (rule *ServersIPV6FirewallRule_Spec) AssignProperties_From_ServersIPV6Firew // EndIPv6Address rule.EndIPv6Address = genruntime.ClonePointerToString(source.EndIPv6Address) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersIPV6FirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -499,6 +562,18 @@ func (rule *ServersIPV6FirewallRule_Spec) AssignProperties_To_ServersIPV6Firewal // EndIPv6Address destination.EndIPv6Address = genruntime.ClonePointerToString(rule.EndIPv6Address) + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.ServersIPV6FirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -731,6 +806,110 @@ func (rule *ServersIPV6FirewallRule_STATUS) AssignProperties_To_ServersIPV6Firew return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersIPV6FirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec populates our ServersIPV6FirewallRuleOperatorSpec from the provided source ServersIPV6FirewallRuleOperatorSpec +func (operator *ServersIPV6FirewallRuleOperatorSpec) AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec(source *storage.ServersIPV6FirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec populates the provided destination ServersIPV6FirewallRuleOperatorSpec from our ServersIPV6FirewallRuleOperatorSpec +func (operator *ServersIPV6FirewallRuleOperatorSpec) AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec(destination *storage.ServersIPV6FirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersIPV6FirewallRule{}, &ServersIPV6FirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen_test.go index b8e9a72c3a8..830ed3ba4fe 100644 --- a/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_ipv_6_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersIPV6FirewallRule(gens map[string]gopt gens["Status"] = ServersIPV6FirewallRule_STATUSGenerator() } +func Test_ServersIPV6FirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersIPV6FirewallRuleOperatorSpec to ServersIPV6FirewallRuleOperatorSpec via AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec & AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersIPV6FirewallRuleOperatorSpec, ServersIPV6FirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersIPV6FirewallRuleOperatorSpec tests if a specific instance of ServersIPV6FirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersIPV6FirewallRuleOperatorSpec(subject ServersIPV6FirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersIPV6FirewallRuleOperatorSpec + err := copied.AssignProperties_To_ServersIPV6FirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersIPV6FirewallRuleOperatorSpec + err = actual.AssignProperties_From_ServersIPV6FirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersIPV6FirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersIPV6FirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec, ServersIPV6FirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec runs a test to see if a specific instance of ServersIPV6FirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec(subject ServersIPV6FirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersIPV6FirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersIPV6FirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersIPV6FirewallRuleOperatorSpecGenerator() +var serversIPV6FirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersIPV6FirewallRuleOperatorSpecGenerator returns a generator of ServersIPV6FirewallRuleOperatorSpec instances for property testing. +func ServersIPV6FirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversIPV6FirewallRuleOperatorSpecGenerator != nil { + return serversIPV6FirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversIPV6FirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRuleOperatorSpec{}), generators) + + return serversIPV6FirewallRuleOperatorSpecGenerator +} + func Test_ServersIPV6FirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -358,6 +455,9 @@ func RunJSONSerializationTestForServersIPV6FirewallRule_Spec(subject ServersIPV6 var serversIPV6FirewallRule_SpecGenerator gopter.Gen // ServersIPV6FirewallRule_SpecGenerator returns a generator of ServersIPV6FirewallRule_Spec instances for property testing. +// We first initialize serversIPV6FirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersIPV6FirewallRule_SpecGenerator() gopter.Gen { if serversIPV6FirewallRule_SpecGenerator != nil { return serversIPV6FirewallRule_SpecGenerator @@ -367,6 +467,12 @@ func ServersIPV6FirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) serversIPV6FirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) + serversIPV6FirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRule_Spec{}), generators) + return serversIPV6FirewallRule_SpecGenerator } @@ -376,3 +482,8 @@ func AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(gens map[st gens["EndIPv6Address"] = gen.PtrOf(gen.AlphaString()) gens["StartIPv6Address"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersIPV6FirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen.go index 0d273528fd6..cb6336ce27c 100644 --- a/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *ServersOutboundFirewallRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersOutboundFirewallRule resource func (rule *ServersOutboundFirewallRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &ServersOutboundFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersOutboundFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersOutboundFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersOutboundFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersOutboundFirewallRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *ServersOutboundFirewallRule) ValidateUpdate(old runtime.Object) (adm // createValidations validates the creation of the resource func (rule *ServersOutboundFirewallRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,9 +250,23 @@ func (rule *ServersOutboundFirewallRule) updateValidations() []func(old runtime. func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *ServersOutboundFirewallRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (rule *ServersOutboundFirewallRule) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(rule) @@ -244,6 +281,14 @@ func (rule *ServersOutboundFirewallRule) validateResourceReferences() (admission return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *ServersOutboundFirewallRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *ServersOutboundFirewallRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersOutboundFirewallRule) @@ -330,6 +375,10 @@ type ServersOutboundFirewallRule_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersOutboundFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -366,6 +415,8 @@ func (rule *ServersOutboundFirewallRule_Spec) PopulateFromARM(owner genruntime.A // Set property "AzureName": rule.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -432,6 +483,18 @@ func (rule *ServersOutboundFirewallRule_Spec) AssignProperties_From_ServersOutbo // AzureName rule.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersOutboundFirewallRuleOperatorSpec + err := operatorSpec.AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -452,6 +515,18 @@ func (rule *ServersOutboundFirewallRule_Spec) AssignProperties_To_ServersOutboun // AzureName destination.AzureName = rule.AzureName + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.ServersOutboundFirewallRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -658,6 +733,110 @@ func (rule *ServersOutboundFirewallRule_STATUS) AssignProperties_To_ServersOutbo return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersOutboundFirewallRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec populates our ServersOutboundFirewallRuleOperatorSpec from the provided source ServersOutboundFirewallRuleOperatorSpec +func (operator *ServersOutboundFirewallRuleOperatorSpec) AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec(source *storage.ServersOutboundFirewallRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec populates the provided destination ServersOutboundFirewallRuleOperatorSpec from our ServersOutboundFirewallRuleOperatorSpec +func (operator *ServersOutboundFirewallRuleOperatorSpec) AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec(destination *storage.ServersOutboundFirewallRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersOutboundFirewallRule{}, &ServersOutboundFirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen_test.go index 35cd07fba09..23144e1ff6d 100644 --- a/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_outbound_firewall_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersOutboundFirewallRule(gens map[string] gens["Status"] = ServersOutboundFirewallRule_STATUSGenerator() } +func Test_ServersOutboundFirewallRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersOutboundFirewallRuleOperatorSpec to ServersOutboundFirewallRuleOperatorSpec via AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec & AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersOutboundFirewallRuleOperatorSpec, ServersOutboundFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersOutboundFirewallRuleOperatorSpec tests if a specific instance of ServersOutboundFirewallRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersOutboundFirewallRuleOperatorSpec(subject ServersOutboundFirewallRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersOutboundFirewallRuleOperatorSpec + err := copied.AssignProperties_To_ServersOutboundFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersOutboundFirewallRuleOperatorSpec + err = actual.AssignProperties_From_ServersOutboundFirewallRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersOutboundFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersOutboundFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec, ServersOutboundFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec runs a test to see if a specific instance of ServersOutboundFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec(subject ServersOutboundFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersOutboundFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersOutboundFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersOutboundFirewallRuleOperatorSpecGenerator() +var serversOutboundFirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersOutboundFirewallRuleOperatorSpecGenerator returns a generator of ServersOutboundFirewallRuleOperatorSpec instances for property testing. +func ServersOutboundFirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversOutboundFirewallRuleOperatorSpecGenerator != nil { + return serversOutboundFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversOutboundFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRuleOperatorSpec{}), generators) + + return serversOutboundFirewallRuleOperatorSpecGenerator +} + func Test_ServersOutboundFirewallRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -357,6 +454,9 @@ func RunJSONSerializationTestForServersOutboundFirewallRule_Spec(subject Servers var serversOutboundFirewallRule_SpecGenerator gopter.Gen // ServersOutboundFirewallRule_SpecGenerator returns a generator of ServersOutboundFirewallRule_Spec instances for property testing. +// We first initialize serversOutboundFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersOutboundFirewallRule_SpecGenerator() gopter.Gen { if serversOutboundFirewallRule_SpecGenerator != nil { return serversOutboundFirewallRule_SpecGenerator @@ -366,6 +466,12 @@ func ServersOutboundFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) serversOutboundFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) + serversOutboundFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRule_Spec{}), generators) + return serversOutboundFirewallRule_SpecGenerator } @@ -373,3 +479,8 @@ func ServersOutboundFirewallRule_SpecGenerator() gopter.Gen { func AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(gens map[string]gopter.Gen) { gens["AzureName"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersOutboundFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen.go b/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen.go index 15d9de7f8fd..b20c44086ed 100644 --- a/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *ServersSecurityAlertPolicy) Default() { // defaultImpl applies the code generated defaults to the ServersSecurityAlertPolicy resource func (policy *ServersSecurityAlertPolicy) defaultImpl() {} +var _ configmaps.Exporter = &ServersSecurityAlertPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersSecurityAlertPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersSecurityAlertPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersSecurityAlertPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersSecurityAlertPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (policy *ServersSecurityAlertPolicy) ValidateUpdate(old runtime.Object) (ad // createValidations validates the creation of the resource func (policy *ServersSecurityAlertPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (policy *ServersSecurityAlertPolicy) updateValidations() []func(old runtime func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *ServersSecurityAlertPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (policy *ServersSecurityAlertPolicy) validateResourceReferences() (admissio return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *ServersSecurityAlertPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *ServersSecurityAlertPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersSecurityAlertPolicy) @@ -328,6 +373,10 @@ type ServersSecurityAlertPolicy_Spec struct { // EmailAddresses: Specifies an array of e-mail addresses to which the alert is sent. EmailAddresses []string `json:"emailAddresses,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersSecurityAlertPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -444,6 +493,8 @@ func (policy *ServersSecurityAlertPolicy_Spec) PopulateFromARM(owner genruntime. } } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -552,6 +603,18 @@ func (policy *ServersSecurityAlertPolicy_Spec) AssignProperties_From_ServersSecu // EmailAddresses policy.EmailAddresses = genruntime.CloneSliceOfString(source.EmailAddresses) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersSecurityAlertPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -606,6 +669,18 @@ func (policy *ServersSecurityAlertPolicy_Spec) AssignProperties_To_ServersSecuri // EmailAddresses destination.EmailAddresses = genruntime.CloneSliceOfString(policy.EmailAddresses) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.ServersSecurityAlertPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -1054,6 +1129,110 @@ var serverSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_STATUS_Value "enabled": ServerSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_STATUS_Enabled, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersSecurityAlertPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec populates our ServersSecurityAlertPolicyOperatorSpec from the provided source ServersSecurityAlertPolicyOperatorSpec +func (operator *ServersSecurityAlertPolicyOperatorSpec) AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec(source *storage.ServersSecurityAlertPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec populates the provided destination ServersSecurityAlertPolicyOperatorSpec from our ServersSecurityAlertPolicyOperatorSpec +func (operator *ServersSecurityAlertPolicyOperatorSpec) AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec(destination *storage.ServersSecurityAlertPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersSecurityAlertPolicy{}, &ServersSecurityAlertPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen_test.go b/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen_test.go index 201d77e1009..670a3aa73ca 100644 --- a/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_security_alert_policy_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy(gens map[string]g gens["Status"] = ServersSecurityAlertPolicy_STATUSGenerator() } +func Test_ServersSecurityAlertPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersSecurityAlertPolicyOperatorSpec to ServersSecurityAlertPolicyOperatorSpec via AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec & AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersSecurityAlertPolicyOperatorSpec, ServersSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersSecurityAlertPolicyOperatorSpec tests if a specific instance of ServersSecurityAlertPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersSecurityAlertPolicyOperatorSpec(subject ServersSecurityAlertPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersSecurityAlertPolicyOperatorSpec + err := copied.AssignProperties_To_ServersSecurityAlertPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersSecurityAlertPolicyOperatorSpec + err = actual.AssignProperties_From_ServersSecurityAlertPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersSecurityAlertPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersSecurityAlertPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec, ServersSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec runs a test to see if a specific instance of ServersSecurityAlertPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec(subject ServersSecurityAlertPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersSecurityAlertPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersSecurityAlertPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersSecurityAlertPolicyOperatorSpecGenerator() +var serversSecurityAlertPolicyOperatorSpecGenerator gopter.Gen + +// ServersSecurityAlertPolicyOperatorSpecGenerator returns a generator of ServersSecurityAlertPolicyOperatorSpec instances for property testing. +func ServersSecurityAlertPolicyOperatorSpecGenerator() gopter.Gen { + if serversSecurityAlertPolicyOperatorSpecGenerator != nil { + return serversSecurityAlertPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversSecurityAlertPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicyOperatorSpec{}), generators) + + return serversSecurityAlertPolicyOperatorSpecGenerator +} + func Test_ServersSecurityAlertPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -377,6 +474,9 @@ func RunJSONSerializationTestForServersSecurityAlertPolicy_Spec(subject ServersS var serversSecurityAlertPolicy_SpecGenerator gopter.Gen // ServersSecurityAlertPolicy_SpecGenerator returns a generator of ServersSecurityAlertPolicy_Spec instances for property testing. +// We first initialize serversSecurityAlertPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersSecurityAlertPolicy_SpecGenerator() gopter.Gen { if serversSecurityAlertPolicy_SpecGenerator != nil { return serversSecurityAlertPolicy_SpecGenerator @@ -386,6 +486,12 @@ func ServersSecurityAlertPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) serversSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) + serversSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicy_Spec{}), generators) + return serversSecurityAlertPolicy_SpecGenerator } @@ -398,3 +504,8 @@ func AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(gens map gens["State"] = gen.PtrOf(gen.OneConstOf(ServerSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_Disabled, ServerSecurityAlertPoliciesSecurityAlertsPolicyProperties_State_Enabled)) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersSecurityAlertPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen.go b/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen.go index 46393201561..a1f24a6ce6b 100644 --- a/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (rule *ServersVirtualNetworkRule) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServersVirtualNetworkRule resource func (rule *ServersVirtualNetworkRule) defaultImpl() { rule.defaultAzureName() } +var _ configmaps.Exporter = &ServersVirtualNetworkRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersVirtualNetworkRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersVirtualNetworkRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersVirtualNetworkRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersVirtualNetworkRule{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (rule *ServersVirtualNetworkRule) ValidateUpdate(old runtime.Object) (admis // createValidations validates the creation of the resource func (rule *ServersVirtualNetworkRule) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference} + return []func() (admission.Warnings, error){rule.validateResourceReferences, rule.validateOwnerReference, rule.validateSecretDestinations, rule.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (rule *ServersVirtualNetworkRule) updateValidations() []func(old runtime.Ob func(old runtime.Object) (admission.Warnings, error) { return rule.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return rule.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (rule *ServersVirtualNetworkRule) validateConfigMapDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (rule *ServersVirtualNetworkRule) validateResourceReferences() (admission.W return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (rule *ServersVirtualNetworkRule) validateSecretDestinations() (admission.Warnings, error) { + if rule.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(rule, nil, rule.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (rule *ServersVirtualNetworkRule) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersVirtualNetworkRule) @@ -333,6 +378,10 @@ type ServersVirtualNetworkRule_Spec struct { // IgnoreMissingVnetServiceEndpoint: Create firewall rule before the virtual network has vnet service endpoint enabled. IgnoreMissingVnetServiceEndpoint *bool `json:"ignoreMissingVnetServiceEndpoint,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersVirtualNetworkRuleOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -399,6 +448,8 @@ func (rule *ServersVirtualNetworkRule_Spec) PopulateFromARM(owner genruntime.Arb } } + // no assignment for property "OperatorSpec" + // Set property "Owner": rule.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -475,6 +526,18 @@ func (rule *ServersVirtualNetworkRule_Spec) AssignProperties_From_ServersVirtual rule.IgnoreMissingVnetServiceEndpoint = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersVirtualNetworkRuleOperatorSpec + err := operatorSpec.AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec() to populate field OperatorSpec") + } + rule.OperatorSpec = &operatorSpec + } else { + rule.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -511,6 +574,18 @@ func (rule *ServersVirtualNetworkRule_Spec) AssignProperties_To_ServersVirtualNe destination.IgnoreMissingVnetServiceEndpoint = nil } + // OperatorSpec + if rule.OperatorSpec != nil { + var operatorSpec storage.ServersVirtualNetworkRuleOperatorSpec + err := rule.OperatorSpec.AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = rule.OriginalVersion() @@ -800,6 +875,110 @@ func (rule *ServersVirtualNetworkRule_STATUS) AssignProperties_To_ServersVirtual return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersVirtualNetworkRuleOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec populates our ServersVirtualNetworkRuleOperatorSpec from the provided source ServersVirtualNetworkRuleOperatorSpec +func (operator *ServersVirtualNetworkRuleOperatorSpec) AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec(source *storage.ServersVirtualNetworkRuleOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec populates the provided destination ServersVirtualNetworkRuleOperatorSpec from our ServersVirtualNetworkRuleOperatorSpec +func (operator *ServersVirtualNetworkRuleOperatorSpec) AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec(destination *storage.ServersVirtualNetworkRuleOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type VirtualNetworkRuleProperties_State_STATUS string const ( diff --git a/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen_test.go b/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen_test.go index 8a9cc643320..4d49658b377 100644 --- a/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_virtual_network_rule_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersVirtualNetworkRule(gens map[string]go gens["Status"] = ServersVirtualNetworkRule_STATUSGenerator() } +func Test_ServersVirtualNetworkRuleOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersVirtualNetworkRuleOperatorSpec to ServersVirtualNetworkRuleOperatorSpec via AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec & AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersVirtualNetworkRuleOperatorSpec, ServersVirtualNetworkRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersVirtualNetworkRuleOperatorSpec tests if a specific instance of ServersVirtualNetworkRuleOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersVirtualNetworkRuleOperatorSpec(subject ServersVirtualNetworkRuleOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersVirtualNetworkRuleOperatorSpec + err := copied.AssignProperties_To_ServersVirtualNetworkRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersVirtualNetworkRuleOperatorSpec + err = actual.AssignProperties_From_ServersVirtualNetworkRuleOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersVirtualNetworkRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersVirtualNetworkRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec, ServersVirtualNetworkRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec runs a test to see if a specific instance of ServersVirtualNetworkRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec(subject ServersVirtualNetworkRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersVirtualNetworkRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersVirtualNetworkRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersVirtualNetworkRuleOperatorSpecGenerator() +var serversVirtualNetworkRuleOperatorSpecGenerator gopter.Gen + +// ServersVirtualNetworkRuleOperatorSpecGenerator returns a generator of ServersVirtualNetworkRuleOperatorSpec instances for property testing. +func ServersVirtualNetworkRuleOperatorSpecGenerator() gopter.Gen { + if serversVirtualNetworkRuleOperatorSpecGenerator != nil { + return serversVirtualNetworkRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversVirtualNetworkRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRuleOperatorSpec{}), generators) + + return serversVirtualNetworkRuleOperatorSpecGenerator +} + func Test_ServersVirtualNetworkRule_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -365,6 +462,9 @@ func RunJSONSerializationTestForServersVirtualNetworkRule_Spec(subject ServersVi var serversVirtualNetworkRule_SpecGenerator gopter.Gen // ServersVirtualNetworkRule_SpecGenerator returns a generator of ServersVirtualNetworkRule_Spec instances for property testing. +// We first initialize serversVirtualNetworkRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersVirtualNetworkRule_SpecGenerator() gopter.Gen { if serversVirtualNetworkRule_SpecGenerator != nil { return serversVirtualNetworkRule_SpecGenerator @@ -374,6 +474,12 @@ func ServersVirtualNetworkRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) serversVirtualNetworkRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) + serversVirtualNetworkRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRule_Spec{}), generators) + return serversVirtualNetworkRule_SpecGenerator } @@ -382,3 +488,8 @@ func AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(gens map[ gens["AzureName"] = gen.AlphaString() gens["IgnoreMissingVnetServiceEndpoint"] = gen.PtrOf(gen.Bool()) } + +// AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersVirtualNetworkRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen.go b/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen.go index c6ef3831f8f..46305f46633 100644 --- a/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen.go +++ b/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +87,26 @@ func (assessment *ServersVulnerabilityAssessment) Default() { // defaultImpl applies the code generated defaults to the ServersVulnerabilityAssessment resource func (assessment *ServersVulnerabilityAssessment) defaultImpl() {} +var _ configmaps.Exporter = &ServersVulnerabilityAssessment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assessment *ServersVulnerabilityAssessment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersVulnerabilityAssessment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assessment *ServersVulnerabilityAssessment) SecretDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServersVulnerabilityAssessment{} // InitializeSpec initializes the spec for this resource from the given status @@ -203,7 +225,7 @@ func (assessment *ServersVulnerabilityAssessment) ValidateUpdate(old runtime.Obj // createValidations validates the creation of the resource func (assessment *ServersVulnerabilityAssessment) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){assessment.validateResourceReferences, assessment.validateOwnerReference, assessment.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){assessment.validateResourceReferences, assessment.validateOwnerReference, assessment.validateSecretDestinations, assessment.validateConfigMapDestinations, assessment.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -221,12 +243,26 @@ func (assessment *ServersVulnerabilityAssessment) updateValidations() []func(old func(old runtime.Object) (admission.Warnings, error) { return assessment.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return assessment.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return assessment.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return assessment.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (assessment *ServersVulnerabilityAssessment) validateConfigMapDestinations() (admission.Warnings, error) { + if assessment.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(assessment, nil, assessment.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (assessment *ServersVulnerabilityAssessment) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&assessment.Spec) @@ -250,6 +286,14 @@ func (assessment *ServersVulnerabilityAssessment) validateResourceReferences() ( return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (assessment *ServersVulnerabilityAssessment) validateSecretDestinations() (admission.Warnings, error) { + if assessment.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(assessment, nil, assessment.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (assessment *ServersVulnerabilityAssessment) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServersVulnerabilityAssessment) @@ -332,6 +376,10 @@ type ServersVulnerabilityAssessmentList struct { } type ServersVulnerabilityAssessment_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServersVulnerabilityAssessmentOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -431,6 +479,8 @@ func (assessment *ServersVulnerabilityAssessment_Spec) PopulateFromARM(owner gen return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.ServersVulnerabilityAssessment_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": assessment.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -523,6 +573,18 @@ func (assessment *ServersVulnerabilityAssessment_Spec) ConvertSpecTo(destination // AssignProperties_From_ServersVulnerabilityAssessment_Spec populates our ServersVulnerabilityAssessment_Spec from the provided source ServersVulnerabilityAssessment_Spec func (assessment *ServersVulnerabilityAssessment_Spec) AssignProperties_From_ServersVulnerabilityAssessment_Spec(source *storage.ServersVulnerabilityAssessment_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServersVulnerabilityAssessmentOperatorSpec + err := operatorSpec.AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec() to populate field OperatorSpec") + } + assessment.OperatorSpec = &operatorSpec + } else { + assessment.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -579,6 +641,18 @@ func (assessment *ServersVulnerabilityAssessment_Spec) AssignProperties_To_Serve // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if assessment.OperatorSpec != nil { + var operatorSpec storage.ServersVulnerabilityAssessmentOperatorSpec + err := assessment.OperatorSpec.AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = assessment.OriginalVersion() @@ -876,6 +950,110 @@ func (assessment *ServersVulnerabilityAssessment_STATUS) AssignProperties_To_Ser return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersVulnerabilityAssessmentOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec populates our ServersVulnerabilityAssessmentOperatorSpec from the provided source ServersVulnerabilityAssessmentOperatorSpec +func (operator *ServersVulnerabilityAssessmentOperatorSpec) AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec(source *storage.ServersVulnerabilityAssessmentOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec populates the provided destination ServersVulnerabilityAssessmentOperatorSpec from our ServersVulnerabilityAssessmentOperatorSpec +func (operator *ServersVulnerabilityAssessmentOperatorSpec) AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec(destination *storage.ServersVulnerabilityAssessmentOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&ServersVulnerabilityAssessment{}, &ServersVulnerabilityAssessmentList{}) } diff --git a/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen_test.go b/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen_test.go index 5ebabcc5ff6..ed68c665993 100644 --- a/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen_test.go +++ b/v2/api/sql/v1api20211101/servers_vulnerability_assessment_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment(gens map[stri gens["Status"] = ServersVulnerabilityAssessment_STATUSGenerator() } +func Test_ServersVulnerabilityAssessmentOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServersVulnerabilityAssessmentOperatorSpec to ServersVulnerabilityAssessmentOperatorSpec via AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec & AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServersVulnerabilityAssessmentOperatorSpec, ServersVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServersVulnerabilityAssessmentOperatorSpec tests if a specific instance of ServersVulnerabilityAssessmentOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServersVulnerabilityAssessmentOperatorSpec(subject ServersVulnerabilityAssessmentOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServersVulnerabilityAssessmentOperatorSpec + err := copied.AssignProperties_To_ServersVulnerabilityAssessmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServersVulnerabilityAssessmentOperatorSpec + err = actual.AssignProperties_From_ServersVulnerabilityAssessmentOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServersVulnerabilityAssessmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersVulnerabilityAssessmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec, ServersVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec runs a test to see if a specific instance of ServersVulnerabilityAssessmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec(subject ServersVulnerabilityAssessmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersVulnerabilityAssessmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersVulnerabilityAssessmentOperatorSpec instances for property testing - lazily instantiated by +// ServersVulnerabilityAssessmentOperatorSpecGenerator() +var serversVulnerabilityAssessmentOperatorSpecGenerator gopter.Gen + +// ServersVulnerabilityAssessmentOperatorSpecGenerator returns a generator of ServersVulnerabilityAssessmentOperatorSpec instances for property testing. +func ServersVulnerabilityAssessmentOperatorSpecGenerator() gopter.Gen { + if serversVulnerabilityAssessmentOperatorSpecGenerator != nil { + return serversVulnerabilityAssessmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversVulnerabilityAssessmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersVulnerabilityAssessmentOperatorSpec{}), generators) + + return serversVulnerabilityAssessmentOperatorSpecGenerator +} + func Test_ServersVulnerabilityAssessment_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,5 +496,6 @@ func AddIndependentPropertyGeneratorsForServersVulnerabilityAssessment_Spec(gens // AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersVulnerabilityAssessmentOperatorSpecGenerator()) gens["RecurringScans"] = gen.PtrOf(VulnerabilityAssessmentRecurringScansPropertiesGenerator()) } diff --git a/v2/api/sql/v1api20211101/storage/server_types_gen.go b/v2/api/sql/v1api20211101/storage/server_types_gen.go index 6c7e85d49c7..a802f52859a 100644 --- a/v2/api/sql/v1api20211101/storage/server_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/server_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (server *Server) SetConditions(conditions conditions.Conditions) { server.Status.Conditions = conditions } +var _ configmaps.Exporter = &Server{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (server *Server) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Server{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (server *Server) SecretDestinationExpressions() []*core.DestinationExpression { + if server.Spec.OperatorSpec == nil { + return nil + } + return server.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Server{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -310,8 +332,10 @@ type ServerExternalAdministrator_STATUS struct { // Storage version of v1api20211101.ServerOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type ServerOperatorSpec struct { - ConfigMaps *ServerOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *ServerOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } // Storage version of v1api20211101.ServerPrivateEndpointConnection_STATUS diff --git a/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen.go index 3400fe7200d..cacc56963dc 100644 --- a/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (administrator *ServersAdministrator) SetConditions(conditions conditions.C administrator.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersAdministrator{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (administrator *ServersAdministrator) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAdministrator{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (administrator *ServersAdministrator) SecretDestinationExpressions() []*core.DestinationExpression { + if administrator.Spec.OperatorSpec == nil { + return nil + } + return administrator.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersAdministrator{} // AzureName returns the Azure name of the resource (always "ActiveDirectory") @@ -140,9 +163,10 @@ type ServersAdministratorList struct { // Storage version of v1api20211101.ServersAdministrator_Spec type ServersAdministrator_Spec struct { - AdministratorType *string `json:"administratorType,omitempty"` - Login *string `json:"login,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AdministratorType *string `json:"administratorType,omitempty"` + Login *string `json:"login,omitempty"` + OperatorSpec *ServersAdministratorOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -210,6 +234,14 @@ func (administrator *ServersAdministrator_STATUS) ConvertStatusTo(destination ge return destination.ConvertStatusFrom(administrator) } +// Storage version of v1api20211101.ServersAdministratorOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAdministratorOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersAdministrator{}, &ServersAdministratorList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen_test.go index cc71caee54c..b6f2fc2ef48 100644 --- a/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_administrator_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersAdministrator(gens map[string]gopter. gens["Status"] = ServersAdministrator_STATUSGenerator() } +func Test_ServersAdministratorOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAdministratorOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAdministratorOperatorSpec, ServersAdministratorOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAdministratorOperatorSpec runs a test to see if a specific instance of ServersAdministratorOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAdministratorOperatorSpec(subject ServersAdministratorOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAdministratorOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAdministratorOperatorSpec instances for property testing - lazily instantiated by +// ServersAdministratorOperatorSpecGenerator() +var serversAdministratorOperatorSpecGenerator gopter.Gen + +// ServersAdministratorOperatorSpecGenerator returns a generator of ServersAdministratorOperatorSpec instances for property testing. +func ServersAdministratorOperatorSpecGenerator() gopter.Gen { + if serversAdministratorOperatorSpecGenerator != nil { + return serversAdministratorOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAdministratorOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministratorOperatorSpec{}), generators) + + return serversAdministratorOperatorSpecGenerator +} + func Test_ServersAdministrator_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -191,6 +246,9 @@ func RunJSONSerializationTestForServersAdministrator_Spec(subject ServersAdminis var serversAdministrator_SpecGenerator gopter.Gen // ServersAdministrator_SpecGenerator returns a generator of ServersAdministrator_Spec instances for property testing. +// We first initialize serversAdministrator_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAdministrator_SpecGenerator() gopter.Gen { if serversAdministrator_SpecGenerator != nil { return serversAdministrator_SpecGenerator @@ -200,6 +258,12 @@ func ServersAdministrator_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAdministrator_Spec(generators) serversAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministrator_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAdministrator_Spec(generators) + AddRelatedPropertyGeneratorsForServersAdministrator_Spec(generators) + serversAdministrator_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdministrator_Spec{}), generators) + return serversAdministrator_SpecGenerator } @@ -211,3 +275,8 @@ func AddIndependentPropertyGeneratorsForServersAdministrator_Spec(gens map[strin gens["Sid"] = gen.PtrOf(gen.AlphaString()) gens["TenantId"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersAdministrator_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAdministrator_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAdministratorOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen.go index dc833ea4b8a..5452db87fd8 100644 --- a/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *ServersAdvancedThreatProtectionSetting) SetConditions(conditions setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersAdvancedThreatProtectionSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersAdvancedThreatProtectionSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAdvancedThreatProtectionSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersAdvancedThreatProtectionSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersAdvancedThreatProtectionSetting{} // AzureName returns the Azure name of the resource (always "Default") @@ -139,7 +162,8 @@ type ServersAdvancedThreatProtectionSettingList struct { // Storage version of v1api20211101.ServersAdvancedThreatProtectionSetting_Spec type ServersAdvancedThreatProtectionSetting_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *ServersAdvancedThreatProtectionSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -202,6 +226,14 @@ func (setting *ServersAdvancedThreatProtectionSetting_STATUS) ConvertStatusTo(de return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20211101.ServersAdvancedThreatProtectionSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAdvancedThreatProtectionSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.SystemData_STATUS // Metadata pertaining to creation and last modification of the resource. type SystemData_STATUS struct { diff --git a/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen_test.go index cbb152c529d..d10fbfca85e 100644 --- a/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_advanced_threat_protection_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting(gens gens["Status"] = ServersAdvancedThreatProtectionSetting_STATUSGenerator() } +func Test_ServersAdvancedThreatProtectionSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAdvancedThreatProtectionSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec, ServersAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec runs a test to see if a specific instance of ServersAdvancedThreatProtectionSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAdvancedThreatProtectionSettingOperatorSpec(subject ServersAdvancedThreatProtectionSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAdvancedThreatProtectionSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAdvancedThreatProtectionSettingOperatorSpec instances for property testing - lazily instantiated +// by ServersAdvancedThreatProtectionSettingOperatorSpecGenerator() +var serversAdvancedThreatProtectionSettingOperatorSpecGenerator gopter.Gen + +// ServersAdvancedThreatProtectionSettingOperatorSpecGenerator returns a generator of ServersAdvancedThreatProtectionSettingOperatorSpec instances for property testing. +func ServersAdvancedThreatProtectionSettingOperatorSpecGenerator() gopter.Gen { + if serversAdvancedThreatProtectionSettingOperatorSpecGenerator != nil { + return serversAdvancedThreatProtectionSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAdvancedThreatProtectionSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSettingOperatorSpec{}), generators) + + return serversAdvancedThreatProtectionSettingOperatorSpecGenerator +} + func Test_ServersAdvancedThreatProtectionSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForServersAdvancedThreatProtectionSetting_Spec(subj var serversAdvancedThreatProtectionSetting_SpecGenerator gopter.Gen // ServersAdvancedThreatProtectionSetting_SpecGenerator returns a generator of ServersAdvancedThreatProtectionSetting_Spec instances for property testing. +// We first initialize serversAdvancedThreatProtectionSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { if serversAdvancedThreatProtectionSetting_SpecGenerator != nil { return serversAdvancedThreatProtectionSetting_SpecGenerator @@ -211,6 +269,12 @@ func ServersAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) serversAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(generators) + serversAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAdvancedThreatProtectionSetting_Spec{}), generators) + return serversAdvancedThreatProtectionSetting_SpecGenerator } @@ -220,6 +284,11 @@ func AddIndependentPropertyGeneratorsForServersAdvancedThreatProtectionSetting_S gens["State"] = gen.PtrOf(gen.AlphaString()) } +// AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAdvancedThreatProtectionSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAdvancedThreatProtectionSettingOperatorSpecGenerator()) +} + func Test_SystemData_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() diff --git a/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen.go index 2779c1c24dd..233149136fb 100644 --- a/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *ServersAuditingSetting) SetConditions(conditions conditions.Condi setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersAuditingSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersAuditingSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAuditingSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersAuditingSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersAuditingSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,12 +162,13 @@ type ServersAuditingSettingList struct { // Storage version of v1api20211101.ServersAuditingSetting_Spec type ServersAuditingSetting_Spec struct { - AuditActionsAndGroups []string `json:"auditActionsAndGroups,omitempty"` - IsAzureMonitorTargetEnabled *bool `json:"isAzureMonitorTargetEnabled,omitempty"` - IsDevopsAuditEnabled *bool `json:"isDevopsAuditEnabled,omitempty"` - IsManagedIdentityInUse *bool `json:"isManagedIdentityInUse,omitempty"` - IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AuditActionsAndGroups []string `json:"auditActionsAndGroups,omitempty"` + IsAzureMonitorTargetEnabled *bool `json:"isAzureMonitorTargetEnabled,omitempty"` + IsDevopsAuditEnabled *bool `json:"isDevopsAuditEnabled,omitempty"` + IsManagedIdentityInUse *bool `json:"isManagedIdentityInUse,omitempty"` + IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` + OperatorSpec *ServersAuditingSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -219,6 +243,14 @@ func (setting *ServersAuditingSetting_STATUS) ConvertStatusTo(destination genrun return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20211101.ServersAuditingSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAuditingSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersAuditingSetting{}, &ServersAuditingSettingList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen_test.go index 4b4f5ac6903..6082207082c 100644 --- a/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_auditing_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersAuditingSetting(gens map[string]gopte gens["Status"] = ServersAuditingSetting_STATUSGenerator() } +func Test_ServersAuditingSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAuditingSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAuditingSettingOperatorSpec, ServersAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAuditingSettingOperatorSpec runs a test to see if a specific instance of ServersAuditingSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAuditingSettingOperatorSpec(subject ServersAuditingSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAuditingSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAuditingSettingOperatorSpec instances for property testing - lazily instantiated by +// ServersAuditingSettingOperatorSpecGenerator() +var serversAuditingSettingOperatorSpecGenerator gopter.Gen + +// ServersAuditingSettingOperatorSpecGenerator returns a generator of ServersAuditingSettingOperatorSpec instances for property testing. +func ServersAuditingSettingOperatorSpecGenerator() gopter.Gen { + if serversAuditingSettingOperatorSpecGenerator != nil { + return serversAuditingSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAuditingSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSettingOperatorSpec{}), generators) + + return serversAuditingSettingOperatorSpecGenerator +} + func Test_ServersAuditingSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -196,6 +251,9 @@ func RunJSONSerializationTestForServersAuditingSetting_Spec(subject ServersAudit var serversAuditingSetting_SpecGenerator gopter.Gen // ServersAuditingSetting_SpecGenerator returns a generator of ServersAuditingSetting_Spec instances for property testing. +// We first initialize serversAuditingSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAuditingSetting_SpecGenerator() gopter.Gen { if serversAuditingSetting_SpecGenerator != nil { return serversAuditingSetting_SpecGenerator @@ -205,6 +263,12 @@ func ServersAuditingSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(generators) serversAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec(generators) + serversAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAuditingSetting_Spec{}), generators) + return serversAuditingSetting_SpecGenerator } @@ -222,3 +286,8 @@ func AddIndependentPropertyGeneratorsForServersAuditingSetting_Spec(gens map[str gens["StorageAccountSubscriptionId"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAuditingSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAuditingSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen.go index f9cad927552..3b287632775 100644 --- a/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (authentication *ServersAzureADOnlyAuthentication) SetConditions(conditions authentication.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersAzureADOnlyAuthentication{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (authentication *ServersAzureADOnlyAuthentication) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if authentication.Spec.OperatorSpec == nil { + return nil + } + return authentication.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersAzureADOnlyAuthentication{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (authentication *ServersAzureADOnlyAuthentication) SecretDestinationExpressions() []*core.DestinationExpression { + if authentication.Spec.OperatorSpec == nil { + return nil + } + return authentication.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersAzureADOnlyAuthentication{} // AzureName returns the Azure name of the resource (always "Default") @@ -140,8 +163,9 @@ type ServersAzureADOnlyAuthenticationList struct { // Storage version of v1api20211101.ServersAzureADOnlyAuthentication_Spec type ServersAzureADOnlyAuthentication_Spec struct { - AzureADOnlyAuthentication *bool `json:"azureADOnlyAuthentication,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureADOnlyAuthentication *bool `json:"azureADOnlyAuthentication,omitempty"` + OperatorSpec *ServersAzureADOnlyAuthenticationOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -201,6 +225,14 @@ func (authentication *ServersAzureADOnlyAuthentication_STATUS) ConvertStatusTo(d return destination.ConvertStatusFrom(authentication) } +// Storage version of v1api20211101.ServersAzureADOnlyAuthenticationOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersAzureADOnlyAuthenticationOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersAzureADOnlyAuthentication{}, &ServersAzureADOnlyAuthenticationList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen_test.go index f69c52004fc..87f841a355a 100644 --- a/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_azure_ad_only_authentication_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication(gens map[st gens["Status"] = ServersAzureADOnlyAuthentication_STATUSGenerator() } +func Test_ServersAzureADOnlyAuthenticationOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersAzureADOnlyAuthenticationOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec, ServersAzureADOnlyAuthenticationOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec runs a test to see if a specific instance of ServersAzureADOnlyAuthenticationOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersAzureADOnlyAuthenticationOperatorSpec(subject ServersAzureADOnlyAuthenticationOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersAzureADOnlyAuthenticationOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersAzureADOnlyAuthenticationOperatorSpec instances for property testing - lazily instantiated by +// ServersAzureADOnlyAuthenticationOperatorSpecGenerator() +var serversAzureADOnlyAuthenticationOperatorSpecGenerator gopter.Gen + +// ServersAzureADOnlyAuthenticationOperatorSpecGenerator returns a generator of ServersAzureADOnlyAuthenticationOperatorSpec instances for property testing. +func ServersAzureADOnlyAuthenticationOperatorSpecGenerator() gopter.Gen { + if serversAzureADOnlyAuthenticationOperatorSpecGenerator != nil { + return serversAzureADOnlyAuthenticationOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversAzureADOnlyAuthenticationOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthenticationOperatorSpec{}), generators) + + return serversAzureADOnlyAuthenticationOperatorSpecGenerator +} + func Test_ServersAzureADOnlyAuthentication_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -187,6 +242,9 @@ func RunJSONSerializationTestForServersAzureADOnlyAuthentication_Spec(subject Se var serversAzureADOnlyAuthentication_SpecGenerator gopter.Gen // ServersAzureADOnlyAuthentication_SpecGenerator returns a generator of ServersAzureADOnlyAuthentication_Spec instances for property testing. +// We first initialize serversAzureADOnlyAuthentication_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersAzureADOnlyAuthentication_SpecGenerator() gopter.Gen { if serversAzureADOnlyAuthentication_SpecGenerator != nil { return serversAzureADOnlyAuthentication_SpecGenerator @@ -196,6 +254,12 @@ func ServersAzureADOnlyAuthentication_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) serversAzureADOnlyAuthentication_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthentication_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) + AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(generators) + serversAzureADOnlyAuthentication_SpecGenerator = gen.Struct(reflect.TypeOf(ServersAzureADOnlyAuthentication_Spec{}), generators) + return serversAzureADOnlyAuthentication_SpecGenerator } @@ -204,3 +268,8 @@ func AddIndependentPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(ge gens["AzureADOnlyAuthentication"] = gen.PtrOf(gen.Bool()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersAzureADOnlyAuthentication_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersAzureADOnlyAuthenticationOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen.go index 4cc9c1e7954..974d0c477c5 100644 --- a/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ServersConnectionPolicy) SetConditions(conditions conditions.Condi policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersConnectionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersConnectionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersConnectionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersConnectionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersConnectionPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type ServersConnectionPolicyList struct { // Storage version of v1api20211101.ServersConnectionPolicy_Spec type ServersConnectionPolicy_Spec struct { - ConnectionType *string `json:"connectionType,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + ConnectionType *string `json:"connectionType,omitempty"` + OperatorSpec *ServersConnectionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -202,6 +226,14 @@ func (policy *ServersConnectionPolicy_STATUS) ConvertStatusTo(destination genrun return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20211101.ServersConnectionPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersConnectionPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersConnectionPolicy{}, &ServersConnectionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen_test.go index dcbf4e2799a..3c6185c5d9c 100644 --- a/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_connection_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersConnectionPolicy(gens map[string]gopt gens["Status"] = ServersConnectionPolicy_STATUSGenerator() } +func Test_ServersConnectionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersConnectionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersConnectionPolicyOperatorSpec, ServersConnectionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersConnectionPolicyOperatorSpec runs a test to see if a specific instance of ServersConnectionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersConnectionPolicyOperatorSpec(subject ServersConnectionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersConnectionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersConnectionPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersConnectionPolicyOperatorSpecGenerator() +var serversConnectionPolicyOperatorSpecGenerator gopter.Gen + +// ServersConnectionPolicyOperatorSpecGenerator returns a generator of ServersConnectionPolicyOperatorSpec instances for property testing. +func ServersConnectionPolicyOperatorSpecGenerator() gopter.Gen { + if serversConnectionPolicyOperatorSpecGenerator != nil { + return serversConnectionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversConnectionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicyOperatorSpec{}), generators) + + return serversConnectionPolicyOperatorSpecGenerator +} + func Test_ServersConnectionPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -189,6 +244,9 @@ func RunJSONSerializationTestForServersConnectionPolicy_Spec(subject ServersConn var serversConnectionPolicy_SpecGenerator gopter.Gen // ServersConnectionPolicy_SpecGenerator returns a generator of ServersConnectionPolicy_Spec instances for property testing. +// We first initialize serversConnectionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersConnectionPolicy_SpecGenerator() gopter.Gen { if serversConnectionPolicy_SpecGenerator != nil { return serversConnectionPolicy_SpecGenerator @@ -198,6 +256,12 @@ func ServersConnectionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(generators) serversConnectionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec(generators) + serversConnectionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersConnectionPolicy_Spec{}), generators) + return serversConnectionPolicy_SpecGenerator } @@ -206,3 +270,8 @@ func AddIndependentPropertyGeneratorsForServersConnectionPolicy_Spec(gens map[st gens["ConnectionType"] = gen.PtrOf(gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersConnectionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersConnectionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_database_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_database_types_gen.go index 1cccf59e8c8..df28e02ada1 100644 --- a/v2/api/sql/v1api20211101/storage/servers_database_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_database_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (database *ServersDatabase) SetConditions(conditions conditions.Conditions) database.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabase{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (database *ServersDatabase) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabase{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (database *ServersDatabase) SecretDestinationExpressions() []*core.DestinationExpression { + if database.Spec.OperatorSpec == nil { + return nil + } + return database.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabase{} // AzureName returns the Azure name of the resource @@ -164,6 +187,7 @@ type ServersDatabase_Spec struct { MaintenanceConfigurationId *string `json:"maintenanceConfigurationId,omitempty"` MaxSizeBytes *int `json:"maxSizeBytes,omitempty"` MinCapacity *float64 `json:"minCapacity,omitempty"` + OperatorSpec *ServersDatabaseOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -325,6 +349,14 @@ type DatabaseIdentity_STATUS struct { UserAssignedIdentities map[string]DatabaseUserIdentity_STATUS `json:"userAssignedIdentities,omitempty"` } +// Storage version of v1api20211101.ServersDatabaseOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabaseOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.Sku // An ARM Resource SKU. type Sku struct { diff --git a/v2/api/sql/v1api20211101/storage/servers_database_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_database_types_gen_test.go index d2c0f638420..0dc2699e503 100644 --- a/v2/api/sql/v1api20211101/storage/servers_database_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_database_types_gen_test.go @@ -292,6 +292,61 @@ func AddRelatedPropertyGeneratorsForServersDatabase(gens map[string]gopter.Gen) gens["Status"] = ServersDatabase_STATUSGenerator() } +func Test_ServersDatabaseOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabaseOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabaseOperatorSpec, ServersDatabaseOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabaseOperatorSpec runs a test to see if a specific instance of ServersDatabaseOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabaseOperatorSpec(subject ServersDatabaseOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabaseOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabaseOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabaseOperatorSpecGenerator() +var serversDatabaseOperatorSpecGenerator gopter.Gen + +// ServersDatabaseOperatorSpecGenerator returns a generator of ServersDatabaseOperatorSpec instances for property testing. +func ServersDatabaseOperatorSpecGenerator() gopter.Gen { + if serversDatabaseOperatorSpecGenerator != nil { + return serversDatabaseOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabaseOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabaseOperatorSpec{}), generators) + + return serversDatabaseOperatorSpecGenerator +} + func Test_ServersDatabase_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -511,6 +566,7 @@ func AddIndependentPropertyGeneratorsForServersDatabase_Spec(gens map[string]gop // AddRelatedPropertyGeneratorsForServersDatabase_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersDatabase_Spec(gens map[string]gopter.Gen) { gens["Identity"] = gen.PtrOf(DatabaseIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServersDatabaseOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen.go index c9610837c0d..e258db3e12c 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting) SetConditions(co setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesAdvancedThreatProtectionSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesAdvancedThreatProtectionSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersDatabasesAdvancedThreatProtectionSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesAdvancedThreatProtectionSetting{} // AzureName returns the Azure name of the resource (always "Default") @@ -139,7 +162,8 @@ type ServersDatabasesAdvancedThreatProtectionSettingList struct { // Storage version of v1api20211101.ServersDatabasesAdvancedThreatProtectionSetting_Spec type ServersDatabasesAdvancedThreatProtectionSetting_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -202,6 +226,14 @@ func (setting *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) ConvertSt return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20211101.ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesAdvancedThreatProtectionSetting{}, &ServersDatabasesAdvancedThreatProtectionSettingList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen_test.go index dd69aeddf8e..b2db97e6b61 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_advanced_threat_protection_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSett gens["Status"] = ServersDatabasesAdvancedThreatProtectionSetting_STATUSGenerator() } +func Test_ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec, ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec runs a test to see if a specific instance of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSettingOperatorSpec(subject ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator() +var serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator gopter.Gen + +// ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator returns a generator of ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec instances for property testing. +func ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator() gopter.Gen { + if serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator != nil { + return serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec{}), generators) + + return serversDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator +} + func Test_ServersDatabasesAdvancedThreatProtectionSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -202,6 +257,9 @@ func RunJSONSerializationTestForServersDatabasesAdvancedThreatProtectionSetting_ var serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator gopter.Gen // ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator returns a generator of ServersDatabasesAdvancedThreatProtectionSetting_Spec instances for property testing. +// We first initialize serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen { if serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator != nil { return serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator @@ -211,6 +269,12 @@ func ServersDatabasesAdvancedThreatProtectionSetting_SpecGenerator() gopter.Gen AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(generators) + serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAdvancedThreatProtectionSetting_Spec{}), generators) + return serversDatabasesAdvancedThreatProtectionSetting_SpecGenerator } @@ -219,3 +283,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesAdvancedThreatProtection gens["OriginalVersion"] = gen.AlphaString() gens["State"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesAdvancedThreatProtectionSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen.go index 916a16c2418..2554278294b 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (setting *ServersDatabasesAuditingSetting) SetConditions(conditions conditi setting.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesAuditingSetting{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (setting *ServersDatabasesAuditingSetting) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesAuditingSetting{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (setting *ServersDatabasesAuditingSetting) SecretDestinationExpressions() []*core.DestinationExpression { + if setting.Spec.OperatorSpec == nil { + return nil + } + return setting.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesAuditingSetting{} // AzureName returns the Azure name of the resource (always "default") @@ -139,11 +162,12 @@ type ServersDatabasesAuditingSettingList struct { // Storage version of v1api20211101.ServersDatabasesAuditingSetting_Spec type ServersDatabasesAuditingSetting_Spec struct { - AuditActionsAndGroups []string `json:"auditActionsAndGroups,omitempty"` - IsAzureMonitorTargetEnabled *bool `json:"isAzureMonitorTargetEnabled,omitempty"` - IsManagedIdentityInUse *bool `json:"isManagedIdentityInUse,omitempty"` - IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AuditActionsAndGroups []string `json:"auditActionsAndGroups,omitempty"` + IsAzureMonitorTargetEnabled *bool `json:"isAzureMonitorTargetEnabled,omitempty"` + IsManagedIdentityInUse *bool `json:"isManagedIdentityInUse,omitempty"` + IsStorageSecondaryKeyInUse *bool `json:"isStorageSecondaryKeyInUse,omitempty"` + OperatorSpec *ServersDatabasesAuditingSettingOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -218,6 +242,14 @@ func (setting *ServersDatabasesAuditingSetting_STATUS) ConvertStatusTo(destinati return destination.ConvertStatusFrom(setting) } +// Storage version of v1api20211101.ServersDatabasesAuditingSettingOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesAuditingSettingOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesAuditingSetting{}, &ServersDatabasesAuditingSettingList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen_test.go index a79c82c6c6b..593318a2e6b 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_auditing_setting_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting(gens map[str gens["Status"] = ServersDatabasesAuditingSetting_STATUSGenerator() } +func Test_ServersDatabasesAuditingSettingOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesAuditingSettingOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec, ServersDatabasesAuditingSettingOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec runs a test to see if a specific instance of ServersDatabasesAuditingSettingOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesAuditingSettingOperatorSpec(subject ServersDatabasesAuditingSettingOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesAuditingSettingOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesAuditingSettingOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabasesAuditingSettingOperatorSpecGenerator() +var serversDatabasesAuditingSettingOperatorSpecGenerator gopter.Gen + +// ServersDatabasesAuditingSettingOperatorSpecGenerator returns a generator of ServersDatabasesAuditingSettingOperatorSpec instances for property testing. +func ServersDatabasesAuditingSettingOperatorSpecGenerator() gopter.Gen { + if serversDatabasesAuditingSettingOperatorSpecGenerator != nil { + return serversDatabasesAuditingSettingOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesAuditingSettingOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSettingOperatorSpec{}), generators) + + return serversDatabasesAuditingSettingOperatorSpecGenerator +} + func Test_ServersDatabasesAuditingSetting_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -196,6 +251,9 @@ func RunJSONSerializationTestForServersDatabasesAuditingSetting_Spec(subject Ser var serversDatabasesAuditingSetting_SpecGenerator gopter.Gen // ServersDatabasesAuditingSetting_SpecGenerator returns a generator of ServersDatabasesAuditingSetting_Spec instances for property testing. +// We first initialize serversDatabasesAuditingSetting_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesAuditingSetting_SpecGenerator() gopter.Gen { if serversDatabasesAuditingSetting_SpecGenerator != nil { return serversDatabasesAuditingSetting_SpecGenerator @@ -205,6 +263,12 @@ func ServersDatabasesAuditingSetting_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) serversDatabasesAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSetting_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(generators) + serversDatabasesAuditingSetting_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesAuditingSetting_Spec{}), generators) + return serversDatabasesAuditingSetting_SpecGenerator } @@ -221,3 +285,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(gen gens["StorageAccountSubscriptionId"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesAuditingSetting_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesAuditingSettingOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen.go index 0060ff2ab34..c130e495c98 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy) SetConditions(condi policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesBackupLongTermRetentionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesBackupLongTermRetentionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesBackupLongTermRetentionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesBackupLongTermRetentionPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type ServersDatabasesBackupLongTermRetentionPolicyList struct { // Storage version of v1api20211101.ServersDatabasesBackupLongTermRetentionPolicy_Spec type ServersDatabasesBackupLongTermRetentionPolicy_Spec struct { - MonthlyRetention *string `json:"monthlyRetention,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + MonthlyRetention *string `json:"monthlyRetention,omitempty"` + OperatorSpec *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (policy *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) ConvertStatu return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20211101.ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesBackupLongTermRetentionPolicy{}, &ServersDatabasesBackupLongTermRetentionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen_test.go index a1a9cb4e49d..8bb94bb6997 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_backup_long_term_retention_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolic gens["Status"] = ServersDatabasesBackupLongTermRetentionPolicy_STATUSGenerator() } +func Test_ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec, ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator() +var serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator returns a generator of ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec instances for property testing. +func ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator != nil { + return serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec{}), generators) + + return serversDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesBackupLongTermRetentionPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -190,6 +245,9 @@ func RunJSONSerializationTestForServersDatabasesBackupLongTermRetentionPolicy_Sp var serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator gopter.Gen // ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator returns a generator of ServersDatabasesBackupLongTermRetentionPolicy_Spec instances for property testing. +// We first initialize serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator() gopter.Gen { if serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator != nil { return serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator @@ -199,6 +257,12 @@ func ServersDatabasesBackupLongTermRetentionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(generators) + serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupLongTermRetentionPolicy_Spec{}), generators) + return serversDatabasesBackupLongTermRetentionPolicy_SpecGenerator } @@ -210,3 +274,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesBackupLongTermRetentionP gens["WeeklyRetention"] = gen.PtrOf(gen.AlphaString()) gens["YearlyRetention"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesBackupLongTermRetentionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen.go index 92dd2b0fed6..07eae2345fe 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy) SetConditions(cond policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesBackupShortTermRetentionPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesBackupShortTermRetentionPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesBackupShortTermRetentionPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesBackupShortTermRetentionPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type ServersDatabasesBackupShortTermRetentionPolicyList struct { // Storage version of v1api20211101.ServersDatabasesBackupShortTermRetentionPolicy_Spec type ServersDatabasesBackupShortTermRetentionPolicy_Spec struct { - DiffBackupIntervalInHours *int `json:"diffBackupIntervalInHours,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + DiffBackupIntervalInHours *int `json:"diffBackupIntervalInHours,omitempty"` + OperatorSpec *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -202,6 +226,14 @@ func (policy *ServersDatabasesBackupShortTermRetentionPolicy_STATUS) ConvertStat return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20211101.ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesBackupShortTermRetentionPolicy{}, &ServersDatabasesBackupShortTermRetentionPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen_test.go index 350fa1ef5fa..5f3cde1c966 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_backup_short_term_retention_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPoli gens["Status"] = ServersDatabasesBackupShortTermRetentionPolicy_STATUSGenerator() } +func Test_ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec, ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicyOperatorSpec(subject ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator() +var serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator returns a generator of ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec instances for property testing. +func ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator != nil { + return serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec{}), generators) + + return serversDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesBackupShortTermRetentionPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForServersDatabasesBackupShortTermRetentionPolicy_S var serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator gopter.Gen // ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator returns a generator of ServersDatabasesBackupShortTermRetentionPolicy_Spec instances for property testing. +// We first initialize serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator() gopter.Gen { if serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator != nil { return serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator @@ -197,6 +255,12 @@ func ServersDatabasesBackupShortTermRetentionPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(generators) + serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesBackupShortTermRetentionPolicy_Spec{}), generators) + return serversDatabasesBackupShortTermRetentionPolicy_SpecGenerator } @@ -206,3 +270,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesBackupShortTermRetention gens["OriginalVersion"] = gen.AlphaString() gens["RetentionDays"] = gen.PtrOf(gen.Int()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesBackupShortTermRetentionPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen.go index 31cd180c305..8c70b01fdb3 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ServersDatabasesSecurityAlertPolicy) SetConditions(conditions cond policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesSecurityAlertPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersDatabasesSecurityAlertPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesSecurityAlertPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersDatabasesSecurityAlertPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesSecurityAlertPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -139,10 +162,11 @@ type ServersDatabasesSecurityAlertPolicyList struct { // Storage version of v1api20211101.ServersDatabasesSecurityAlertPolicy_Spec type ServersDatabasesSecurityAlertPolicy_Spec struct { - DisabledAlerts []string `json:"disabledAlerts,omitempty"` - EmailAccountAdmins *bool `json:"emailAccountAdmins,omitempty"` - EmailAddresses []string `json:"emailAddresses,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + DisabledAlerts []string `json:"disabledAlerts,omitempty"` + EmailAccountAdmins *bool `json:"emailAccountAdmins,omitempty"` + EmailAddresses []string `json:"emailAddresses,omitempty"` + OperatorSpec *ServersDatabasesSecurityAlertPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -213,6 +237,14 @@ func (policy *ServersDatabasesSecurityAlertPolicy_STATUS) ConvertStatusTo(destin return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20211101.ServersDatabasesSecurityAlertPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesSecurityAlertPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesSecurityAlertPolicy{}, &ServersDatabasesSecurityAlertPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen_test.go index ee8c30cd376..44154978770 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_security_alert_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy(gens map gens["Status"] = ServersDatabasesSecurityAlertPolicy_STATUSGenerator() } +func Test_ServersDatabasesSecurityAlertPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesSecurityAlertPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec, ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec runs a test to see if a specific instance of ServersDatabasesSecurityAlertPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesSecurityAlertPolicyOperatorSpec(subject ServersDatabasesSecurityAlertPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesSecurityAlertPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesSecurityAlertPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator() +var serversDatabasesSecurityAlertPolicyOperatorSpecGenerator gopter.Gen + +// ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator returns a generator of ServersDatabasesSecurityAlertPolicyOperatorSpec instances for property testing. +func ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator() gopter.Gen { + if serversDatabasesSecurityAlertPolicyOperatorSpecGenerator != nil { + return serversDatabasesSecurityAlertPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesSecurityAlertPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicyOperatorSpec{}), generators) + + return serversDatabasesSecurityAlertPolicyOperatorSpecGenerator +} + func Test_ServersDatabasesSecurityAlertPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -207,6 +262,9 @@ func RunJSONSerializationTestForServersDatabasesSecurityAlertPolicy_Spec(subject var serversDatabasesSecurityAlertPolicy_SpecGenerator gopter.Gen // ServersDatabasesSecurityAlertPolicy_SpecGenerator returns a generator of ServersDatabasesSecurityAlertPolicy_Spec instances for property testing. +// We first initialize serversDatabasesSecurityAlertPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesSecurityAlertPolicy_SpecGenerator() gopter.Gen { if serversDatabasesSecurityAlertPolicy_SpecGenerator != nil { return serversDatabasesSecurityAlertPolicy_SpecGenerator @@ -216,6 +274,12 @@ func ServersDatabasesSecurityAlertPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) serversDatabasesSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(generators) + serversDatabasesSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesSecurityAlertPolicy_Spec{}), generators) + return serversDatabasesSecurityAlertPolicy_SpecGenerator } @@ -229,3 +293,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec gens["State"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesSecurityAlertPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesSecurityAlertPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen.go index 8b516917393..a1fb70771d3 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (encryption *ServersDatabasesTransparentDataEncryption) SetConditions(condi encryption.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesTransparentDataEncryption{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (encryption *ServersDatabasesTransparentDataEncryption) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if encryption.Spec.OperatorSpec == nil { + return nil + } + return encryption.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesTransparentDataEncryption{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (encryption *ServersDatabasesTransparentDataEncryption) SecretDestinationExpressions() []*core.DestinationExpression { + if encryption.Spec.OperatorSpec == nil { + return nil + } + return encryption.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesTransparentDataEncryption{} // AzureName returns the Azure name of the resource (always "current") @@ -139,7 +162,8 @@ type ServersDatabasesTransparentDataEncryptionList struct { // Storage version of v1api20211101.ServersDatabasesTransparentDataEncryption_Spec type ServersDatabasesTransparentDataEncryption_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *ServersDatabasesTransparentDataEncryptionOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -200,6 +224,14 @@ func (encryption *ServersDatabasesTransparentDataEncryption_STATUS) ConvertStatu return destination.ConvertStatusFrom(encryption) } +// Storage version of v1api20211101.ServersDatabasesTransparentDataEncryptionOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesTransparentDataEncryptionOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersDatabasesTransparentDataEncryption{}, &ServersDatabasesTransparentDataEncryptionList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen_test.go index 047e2ff73c6..402adaaffff 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_transparent_data_encryption_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption(ge gens["Status"] = ServersDatabasesTransparentDataEncryption_STATUSGenerator() } +func Test_ServersDatabasesTransparentDataEncryptionOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesTransparentDataEncryptionOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec, ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec runs a test to see if a specific instance of ServersDatabasesTransparentDataEncryptionOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesTransparentDataEncryptionOperatorSpec(subject ServersDatabasesTransparentDataEncryptionOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesTransparentDataEncryptionOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesTransparentDataEncryptionOperatorSpec instances for property testing - lazily +// instantiated by ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator() +var serversDatabasesTransparentDataEncryptionOperatorSpecGenerator gopter.Gen + +// ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator returns a generator of ServersDatabasesTransparentDataEncryptionOperatorSpec instances for property testing. +func ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator() gopter.Gen { + if serversDatabasesTransparentDataEncryptionOperatorSpecGenerator != nil { + return serversDatabasesTransparentDataEncryptionOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesTransparentDataEncryptionOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryptionOperatorSpec{}), generators) + + return serversDatabasesTransparentDataEncryptionOperatorSpecGenerator +} + func Test_ServersDatabasesTransparentDataEncryption_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -187,6 +242,9 @@ func RunJSONSerializationTestForServersDatabasesTransparentDataEncryption_Spec(s var serversDatabasesTransparentDataEncryption_SpecGenerator gopter.Gen // ServersDatabasesTransparentDataEncryption_SpecGenerator returns a generator of ServersDatabasesTransparentDataEncryption_Spec instances for property testing. +// We first initialize serversDatabasesTransparentDataEncryption_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersDatabasesTransparentDataEncryption_SpecGenerator() gopter.Gen { if serversDatabasesTransparentDataEncryption_SpecGenerator != nil { return serversDatabasesTransparentDataEncryption_SpecGenerator @@ -196,6 +254,12 @@ func ServersDatabasesTransparentDataEncryption_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) serversDatabasesTransparentDataEncryption_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryption_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) + AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(generators) + serversDatabasesTransparentDataEncryption_SpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesTransparentDataEncryption_Spec{}), generators) + return serversDatabasesTransparentDataEncryption_SpecGenerator } @@ -204,3 +268,8 @@ func AddIndependentPropertyGeneratorsForServersDatabasesTransparentDataEncryptio gens["OriginalVersion"] = gen.AlphaString() gens["State"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersDatabasesTransparentDataEncryption_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesTransparentDataEncryptionOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen.go index 8b764d49fca..773b095f1d0 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (assessment *ServersDatabasesVulnerabilityAssessment) SetConditions(conditi assessment.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersDatabasesVulnerabilityAssessment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assessment *ServersDatabasesVulnerabilityAssessment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersDatabasesVulnerabilityAssessment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assessment *ServersDatabasesVulnerabilityAssessment) SecretDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersDatabasesVulnerabilityAssessment{} // AzureName returns the Azure name of the resource (always "default") @@ -140,7 +163,8 @@ type ServersDatabasesVulnerabilityAssessmentList struct { // Storage version of v1api20211101.ServersDatabasesVulnerabilityAssessment_Spec type ServersDatabasesVulnerabilityAssessment_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *ServersDatabasesVulnerabilityAssessmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (assessment *ServersDatabasesVulnerabilityAssessment_STATUS) ConvertStatusT return destination.ConvertStatusFrom(assessment) } +// Storage version of v1api20211101.ServersDatabasesVulnerabilityAssessmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersDatabasesVulnerabilityAssessmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211101.VulnerabilityAssessmentRecurringScansProperties // Properties of a Vulnerability Assessment recurring scans. type VulnerabilityAssessmentRecurringScansProperties struct { diff --git a/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen_test.go index d3af884cca3..ae8d9e3882f 100644 --- a/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_databases_vulnerability_assessment_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment(gens gens["Status"] = ServersDatabasesVulnerabilityAssessment_STATUSGenerator() } +func Test_ServersDatabasesVulnerabilityAssessmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersDatabasesVulnerabilityAssessmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec, ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec runs a test to see if a specific instance of ServersDatabasesVulnerabilityAssessmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersDatabasesVulnerabilityAssessmentOperatorSpec(subject ServersDatabasesVulnerabilityAssessmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersDatabasesVulnerabilityAssessmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersDatabasesVulnerabilityAssessmentOperatorSpec instances for property testing - lazily instantiated +// by ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator() +var serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator gopter.Gen + +// ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator returns a generator of ServersDatabasesVulnerabilityAssessmentOperatorSpec instances for property testing. +func ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator() gopter.Gen { + if serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator != nil { + return serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersDatabasesVulnerabilityAssessmentOperatorSpec{}), generators) + + return serversDatabasesVulnerabilityAssessmentOperatorSpecGenerator +} + func Test_ServersDatabasesVulnerabilityAssessment_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -230,6 +285,7 @@ func AddIndependentPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_ // AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersDatabasesVulnerabilityAssessment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersDatabasesVulnerabilityAssessmentOperatorSpecGenerator()) gens["RecurringScans"] = gen.PtrOf(VulnerabilityAssessmentRecurringScansPropertiesGenerator()) } diff --git a/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen.go index b96c819eeca..02a42b9c23d 100644 --- a/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (pool *ServersElasticPool) SetConditions(conditions conditions.Conditions) pool.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersElasticPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *ServersElasticPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersElasticPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *ServersElasticPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersElasticPool{} // AzureName returns the Azure name of the resource @@ -142,14 +165,15 @@ type ServersElasticPoolList struct { type ServersElasticPool_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - HighAvailabilityReplicaCount *int `json:"highAvailabilityReplicaCount,omitempty"` - LicenseType *string `json:"licenseType,omitempty"` - Location *string `json:"location,omitempty"` - MaintenanceConfigurationId *string `json:"maintenanceConfigurationId,omitempty"` - MaxSizeBytes *int `json:"maxSizeBytes,omitempty"` - MinCapacity *float64 `json:"minCapacity,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + HighAvailabilityReplicaCount *int `json:"highAvailabilityReplicaCount,omitempty"` + LicenseType *string `json:"licenseType,omitempty"` + Location *string `json:"location,omitempty"` + MaintenanceConfigurationId *string `json:"maintenanceConfigurationId,omitempty"` + MaxSizeBytes *int `json:"maxSizeBytes,omitempty"` + MinCapacity *float64 `json:"minCapacity,omitempty"` + OperatorSpec *ServersElasticPoolOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -241,6 +265,14 @@ type ElasticPoolPerDatabaseSettings_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20211101.ServersElasticPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersElasticPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersElasticPool{}, &ServersElasticPoolList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen_test.go index 50fb2ea253c..b5a1c0622d0 100644 --- a/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_elastic_pool_types_gen_test.go @@ -202,6 +202,61 @@ func AddRelatedPropertyGeneratorsForServersElasticPool(gens map[string]gopter.Ge gens["Status"] = ServersElasticPool_STATUSGenerator() } +func Test_ServersElasticPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersElasticPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersElasticPoolOperatorSpec, ServersElasticPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersElasticPoolOperatorSpec runs a test to see if a specific instance of ServersElasticPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersElasticPoolOperatorSpec(subject ServersElasticPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersElasticPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersElasticPoolOperatorSpec instances for property testing - lazily instantiated by +// ServersElasticPoolOperatorSpecGenerator() +var serversElasticPoolOperatorSpecGenerator gopter.Gen + +// ServersElasticPoolOperatorSpecGenerator returns a generator of ServersElasticPoolOperatorSpec instances for property testing. +func ServersElasticPoolOperatorSpecGenerator() gopter.Gen { + if serversElasticPoolOperatorSpecGenerator != nil { + return serversElasticPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversElasticPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersElasticPoolOperatorSpec{}), generators) + + return serversElasticPoolOperatorSpecGenerator +} + func Test_ServersElasticPool_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -376,6 +431,7 @@ func AddIndependentPropertyGeneratorsForServersElasticPool_Spec(gens map[string] // AddRelatedPropertyGeneratorsForServersElasticPool_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersElasticPool_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersElasticPoolOperatorSpecGenerator()) gens["PerDatabaseSettings"] = gen.PtrOf(ElasticPoolPerDatabaseSettingsGenerator()) gens["Sku"] = gen.PtrOf(SkuGenerator()) } diff --git a/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen.go index 9bd66876af6..dbe2d56af12 100644 --- a/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (group *ServersFailoverGroup) SetConditions(conditions conditions.Condition group.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersFailoverGroup{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (group *ServersFailoverGroup) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersFailoverGroup{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (group *ServersFailoverGroup) SecretDestinationExpressions() []*core.DestinationExpression { + if group.Spec.OperatorSpec == nil { + return nil + } + return group.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersFailoverGroup{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type ServersFailoverGroupList struct { type ServersFailoverGroup_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DatabasesReferences []genruntime.ResourceReference `armReference:"Databases" json:"databasesReferences,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DatabasesReferences []genruntime.ResourceReference `armReference:"Databases" json:"databasesReferences,omitempty"` + OperatorSpec *ServersFailoverGroupOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -264,6 +288,14 @@ type PartnerInfo_STATUS struct { ReplicationRole *string `json:"replicationRole,omitempty"` } +// Storage version of v1api20211101.ServersFailoverGroupOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersFailoverGroupOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersFailoverGroup{}, &ServersFailoverGroupList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen_test.go index 7dd69a65c1d..aeeb1043c13 100644 --- a/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_failover_group_types_gen_test.go @@ -441,6 +441,61 @@ func AddRelatedPropertyGeneratorsForServersFailoverGroup(gens map[string]gopter. gens["Status"] = ServersFailoverGroup_STATUSGenerator() } +func Test_ServersFailoverGroupOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersFailoverGroupOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersFailoverGroupOperatorSpec, ServersFailoverGroupOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersFailoverGroupOperatorSpec runs a test to see if a specific instance of ServersFailoverGroupOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersFailoverGroupOperatorSpec(subject ServersFailoverGroupOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersFailoverGroupOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersFailoverGroupOperatorSpec instances for property testing - lazily instantiated by +// ServersFailoverGroupOperatorSpecGenerator() +var serversFailoverGroupOperatorSpecGenerator gopter.Gen + +// ServersFailoverGroupOperatorSpecGenerator returns a generator of ServersFailoverGroupOperatorSpec instances for property testing. +func ServersFailoverGroupOperatorSpecGenerator() gopter.Gen { + if serversFailoverGroupOperatorSpecGenerator != nil { + return serversFailoverGroupOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversFailoverGroupOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersFailoverGroupOperatorSpec{}), generators) + + return serversFailoverGroupOperatorSpecGenerator +} + func Test_ServersFailoverGroup_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -603,6 +658,7 @@ func AddIndependentPropertyGeneratorsForServersFailoverGroup_Spec(gens map[strin // AddRelatedPropertyGeneratorsForServersFailoverGroup_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersFailoverGroup_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersFailoverGroupOperatorSpecGenerator()) gens["PartnerServers"] = gen.SliceOf(PartnerInfoGenerator()) gens["ReadOnlyEndpoint"] = gen.PtrOf(FailoverGroupReadOnlyEndpointGenerator()) gens["ReadWriteEndpoint"] = gen.PtrOf(FailoverGroupReadWriteEndpointGenerator()) diff --git a/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen.go index 54076892ba1..da8de241861 100644 --- a/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *ServersFirewallRule) SetConditions(conditions conditions.Conditions) rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersFirewallRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type ServersFirewallRuleList struct { type ServersFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIpAddress *string `json:"endIpAddress,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIpAddress *string `json:"endIpAddress,omitempty"` + OperatorSpec *ServersFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (rule *ServersFirewallRule_STATUS) ConvertStatusTo(destination genruntime.C return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20211101.ServersFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersFirewallRule{}, &ServersFirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen_test.go index 088f6ae97cd..b5e4eebcd89 100644 --- a/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_firewall_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersFirewallRule(gens map[string]gopter.G gens["Status"] = ServersFirewallRule_STATUSGenerator() } +func Test_ServersFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersFirewallRuleOperatorSpec, ServersFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersFirewallRuleOperatorSpec runs a test to see if a specific instance of ServersFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersFirewallRuleOperatorSpec(subject ServersFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersFirewallRuleOperatorSpecGenerator() +var serversFirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersFirewallRuleOperatorSpecGenerator returns a generator of ServersFirewallRuleOperatorSpec instances for property testing. +func ServersFirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversFirewallRuleOperatorSpecGenerator != nil { + return serversFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRuleOperatorSpec{}), generators) + + return serversFirewallRuleOperatorSpecGenerator +} + func Test_ServersFirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForServersFirewallRule_Spec(subject ServersFirewall var serversFirewallRule_SpecGenerator gopter.Gen // ServersFirewallRule_SpecGenerator returns a generator of ServersFirewallRule_Spec instances for property testing. +// We first initialize serversFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersFirewallRule_SpecGenerator() gopter.Gen { if serversFirewallRule_SpecGenerator != nil { return serversFirewallRule_SpecGenerator @@ -197,6 +255,12 @@ func ServersFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(generators) serversFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersFirewallRule_Spec(generators) + serversFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersFirewallRule_Spec{}), generators) + return serversFirewallRule_SpecGenerator } @@ -207,3 +271,8 @@ func AddIndependentPropertyGeneratorsForServersFirewallRule_Spec(gens map[string gens["OriginalVersion"] = gen.AlphaString() gens["StartIpAddress"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen.go index 13c6035abef..978237fd2f1 100644 --- a/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *ServersIPV6FirewallRule) SetConditions(conditions conditions.Conditi rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersIPV6FirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersIPV6FirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersIPV6FirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersIPV6FirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersIPV6FirewallRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type ServersIPV6FirewallRuleList struct { type ServersIPV6FirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EndIPv6Address *string `json:"endIPv6Address,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EndIPv6Address *string `json:"endIPv6Address,omitempty"` + OperatorSpec *ServersIPV6FirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (rule *ServersIPV6FirewallRule_STATUS) ConvertStatusTo(destination genrunti return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20211101.ServersIPV6FirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersIPV6FirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersIPV6FirewallRule{}, &ServersIPV6FirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen_test.go index 48c33fb0fa9..48b02c7333f 100644 --- a/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_ipv_6_firewall_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersIPV6FirewallRule(gens map[string]gopt gens["Status"] = ServersIPV6FirewallRule_STATUSGenerator() } +func Test_ServersIPV6FirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersIPV6FirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec, ServersIPV6FirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec runs a test to see if a specific instance of ServersIPV6FirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersIPV6FirewallRuleOperatorSpec(subject ServersIPV6FirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersIPV6FirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersIPV6FirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersIPV6FirewallRuleOperatorSpecGenerator() +var serversIPV6FirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersIPV6FirewallRuleOperatorSpecGenerator returns a generator of ServersIPV6FirewallRuleOperatorSpec instances for property testing. +func ServersIPV6FirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversIPV6FirewallRuleOperatorSpecGenerator != nil { + return serversIPV6FirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversIPV6FirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRuleOperatorSpec{}), generators) + + return serversIPV6FirewallRuleOperatorSpecGenerator +} + func Test_ServersIPV6FirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -188,6 +243,9 @@ func RunJSONSerializationTestForServersIPV6FirewallRule_Spec(subject ServersIPV6 var serversIPV6FirewallRule_SpecGenerator gopter.Gen // ServersIPV6FirewallRule_SpecGenerator returns a generator of ServersIPV6FirewallRule_Spec instances for property testing. +// We first initialize serversIPV6FirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersIPV6FirewallRule_SpecGenerator() gopter.Gen { if serversIPV6FirewallRule_SpecGenerator != nil { return serversIPV6FirewallRule_SpecGenerator @@ -197,6 +255,12 @@ func ServersIPV6FirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) serversIPV6FirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec(generators) + serversIPV6FirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersIPV6FirewallRule_Spec{}), generators) + return serversIPV6FirewallRule_SpecGenerator } @@ -207,3 +271,8 @@ func AddIndependentPropertyGeneratorsForServersIPV6FirewallRule_Spec(gens map[st gens["OriginalVersion"] = gen.AlphaString() gens["StartIPv6Address"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersIPV6FirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersIPV6FirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen.go index 7ee9cc80780..e0a86042a91 100644 --- a/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *ServersOutboundFirewallRule) SetConditions(conditions conditions.Con rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersOutboundFirewallRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersOutboundFirewallRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersOutboundFirewallRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersOutboundFirewallRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersOutboundFirewallRule{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type ServersOutboundFirewallRuleList struct { type ServersOutboundFirewallRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *ServersOutboundFirewallRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -203,6 +227,14 @@ func (rule *ServersOutboundFirewallRule_STATUS) ConvertStatusTo(destination genr return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20211101.ServersOutboundFirewallRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersOutboundFirewallRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersOutboundFirewallRule{}, &ServersOutboundFirewallRuleList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen_test.go index 9a77a397ee7..ff881da16a8 100644 --- a/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_outbound_firewall_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersOutboundFirewallRule(gens map[string] gens["Status"] = ServersOutboundFirewallRule_STATUSGenerator() } +func Test_ServersOutboundFirewallRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersOutboundFirewallRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec, ServersOutboundFirewallRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec runs a test to see if a specific instance of ServersOutboundFirewallRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersOutboundFirewallRuleOperatorSpec(subject ServersOutboundFirewallRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersOutboundFirewallRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersOutboundFirewallRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersOutboundFirewallRuleOperatorSpecGenerator() +var serversOutboundFirewallRuleOperatorSpecGenerator gopter.Gen + +// ServersOutboundFirewallRuleOperatorSpecGenerator returns a generator of ServersOutboundFirewallRuleOperatorSpec instances for property testing. +func ServersOutboundFirewallRuleOperatorSpecGenerator() gopter.Gen { + if serversOutboundFirewallRuleOperatorSpecGenerator != nil { + return serversOutboundFirewallRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversOutboundFirewallRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRuleOperatorSpec{}), generators) + + return serversOutboundFirewallRuleOperatorSpecGenerator +} + func Test_ServersOutboundFirewallRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -187,6 +242,9 @@ func RunJSONSerializationTestForServersOutboundFirewallRule_Spec(subject Servers var serversOutboundFirewallRule_SpecGenerator gopter.Gen // ServersOutboundFirewallRule_SpecGenerator returns a generator of ServersOutboundFirewallRule_Spec instances for property testing. +// We first initialize serversOutboundFirewallRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersOutboundFirewallRule_SpecGenerator() gopter.Gen { if serversOutboundFirewallRule_SpecGenerator != nil { return serversOutboundFirewallRule_SpecGenerator @@ -196,6 +254,12 @@ func ServersOutboundFirewallRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) serversOutboundFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec(generators) + serversOutboundFirewallRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersOutboundFirewallRule_Spec{}), generators) + return serversOutboundFirewallRule_SpecGenerator } @@ -204,3 +268,8 @@ func AddIndependentPropertyGeneratorsForServersOutboundFirewallRule_Spec(gens ma gens["AzureName"] = gen.AlphaString() gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersOutboundFirewallRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersOutboundFirewallRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen.go index 4d23075378c..614db42dec0 100644 --- a/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *ServersSecurityAlertPolicy) SetConditions(conditions conditions.Co policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersSecurityAlertPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *ServersSecurityAlertPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersSecurityAlertPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *ServersSecurityAlertPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersSecurityAlertPolicy{} // AzureName returns the Azure name of the resource (always "Default") @@ -139,10 +162,11 @@ type ServersSecurityAlertPolicyList struct { // Storage version of v1api20211101.ServersSecurityAlertPolicy_Spec type ServersSecurityAlertPolicy_Spec struct { - DisabledAlerts []string `json:"disabledAlerts,omitempty"` - EmailAccountAdmins *bool `json:"emailAccountAdmins,omitempty"` - EmailAddresses []string `json:"emailAddresses,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + DisabledAlerts []string `json:"disabledAlerts,omitempty"` + EmailAccountAdmins *bool `json:"emailAccountAdmins,omitempty"` + EmailAddresses []string `json:"emailAddresses,omitempty"` + OperatorSpec *ServersSecurityAlertPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -213,6 +237,14 @@ func (policy *ServersSecurityAlertPolicy_STATUS) ConvertStatusTo(destination gen return destination.ConvertStatusFrom(policy) } +// Storage version of v1api20211101.ServersSecurityAlertPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersSecurityAlertPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersSecurityAlertPolicy{}, &ServersSecurityAlertPolicyList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen_test.go index 0bd3d1f16e2..2a439e49eee 100644 --- a/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_security_alert_policy_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy(gens map[string]g gens["Status"] = ServersSecurityAlertPolicy_STATUSGenerator() } +func Test_ServersSecurityAlertPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersSecurityAlertPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec, ServersSecurityAlertPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec runs a test to see if a specific instance of ServersSecurityAlertPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersSecurityAlertPolicyOperatorSpec(subject ServersSecurityAlertPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersSecurityAlertPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersSecurityAlertPolicyOperatorSpec instances for property testing - lazily instantiated by +// ServersSecurityAlertPolicyOperatorSpecGenerator() +var serversSecurityAlertPolicyOperatorSpecGenerator gopter.Gen + +// ServersSecurityAlertPolicyOperatorSpecGenerator returns a generator of ServersSecurityAlertPolicyOperatorSpec instances for property testing. +func ServersSecurityAlertPolicyOperatorSpecGenerator() gopter.Gen { + if serversSecurityAlertPolicyOperatorSpecGenerator != nil { + return serversSecurityAlertPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversSecurityAlertPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicyOperatorSpec{}), generators) + + return serversSecurityAlertPolicyOperatorSpecGenerator +} + func Test_ServersSecurityAlertPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -207,6 +262,9 @@ func RunJSONSerializationTestForServersSecurityAlertPolicy_Spec(subject ServersS var serversSecurityAlertPolicy_SpecGenerator gopter.Gen // ServersSecurityAlertPolicy_SpecGenerator returns a generator of ServersSecurityAlertPolicy_Spec instances for property testing. +// We first initialize serversSecurityAlertPolicy_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersSecurityAlertPolicy_SpecGenerator() gopter.Gen { if serversSecurityAlertPolicy_SpecGenerator != nil { return serversSecurityAlertPolicy_SpecGenerator @@ -216,6 +274,12 @@ func ServersSecurityAlertPolicy_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) serversSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicy_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) + AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec(generators) + serversSecurityAlertPolicy_SpecGenerator = gen.Struct(reflect.TypeOf(ServersSecurityAlertPolicy_Spec{}), generators) + return serversSecurityAlertPolicy_SpecGenerator } @@ -229,3 +293,8 @@ func AddIndependentPropertyGeneratorsForServersSecurityAlertPolicy_Spec(gens map gens["State"] = gen.PtrOf(gen.AlphaString()) gens["StorageEndpoint"] = gen.PtrOf(gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersSecurityAlertPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersSecurityAlertPolicyOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen.go index 8b3bf242563..81c9f6d658c 100644 --- a/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (rule *ServersVirtualNetworkRule) SetConditions(conditions conditions.Condi rule.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersVirtualNetworkRule{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (rule *ServersVirtualNetworkRule) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersVirtualNetworkRule{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (rule *ServersVirtualNetworkRule) SecretDestinationExpressions() []*core.DestinationExpression { + if rule.Spec.OperatorSpec == nil { + return nil + } + return rule.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersVirtualNetworkRule{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type ServersVirtualNetworkRuleList struct { type ServersVirtualNetworkRule_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - IgnoreMissingVnetServiceEndpoint *bool `json:"ignoreMissingVnetServiceEndpoint,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + IgnoreMissingVnetServiceEndpoint *bool `json:"ignoreMissingVnetServiceEndpoint,omitempty"` + OperatorSpec *ServersVirtualNetworkRuleOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -210,6 +234,14 @@ func (rule *ServersVirtualNetworkRule_STATUS) ConvertStatusTo(destination genrun return destination.ConvertStatusFrom(rule) } +// Storage version of v1api20211101.ServersVirtualNetworkRuleOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersVirtualNetworkRuleOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersVirtualNetworkRule{}, &ServersVirtualNetworkRuleList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen_test.go index a5e67f164c5..298fd640b32 100644 --- a/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_virtual_network_rule_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersVirtualNetworkRule(gens map[string]go gens["Status"] = ServersVirtualNetworkRule_STATUSGenerator() } +func Test_ServersVirtualNetworkRuleOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersVirtualNetworkRuleOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec, ServersVirtualNetworkRuleOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec runs a test to see if a specific instance of ServersVirtualNetworkRuleOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersVirtualNetworkRuleOperatorSpec(subject ServersVirtualNetworkRuleOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersVirtualNetworkRuleOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersVirtualNetworkRuleOperatorSpec instances for property testing - lazily instantiated by +// ServersVirtualNetworkRuleOperatorSpecGenerator() +var serversVirtualNetworkRuleOperatorSpecGenerator gopter.Gen + +// ServersVirtualNetworkRuleOperatorSpecGenerator returns a generator of ServersVirtualNetworkRuleOperatorSpec instances for property testing. +func ServersVirtualNetworkRuleOperatorSpecGenerator() gopter.Gen { + if serversVirtualNetworkRuleOperatorSpecGenerator != nil { + return serversVirtualNetworkRuleOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversVirtualNetworkRuleOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRuleOperatorSpec{}), generators) + + return serversVirtualNetworkRuleOperatorSpecGenerator +} + func Test_ServersVirtualNetworkRule_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -189,6 +244,9 @@ func RunJSONSerializationTestForServersVirtualNetworkRule_Spec(subject ServersVi var serversVirtualNetworkRule_SpecGenerator gopter.Gen // ServersVirtualNetworkRule_SpecGenerator returns a generator of ServersVirtualNetworkRule_Spec instances for property testing. +// We first initialize serversVirtualNetworkRule_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func ServersVirtualNetworkRule_SpecGenerator() gopter.Gen { if serversVirtualNetworkRule_SpecGenerator != nil { return serversVirtualNetworkRule_SpecGenerator @@ -198,6 +256,12 @@ func ServersVirtualNetworkRule_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) serversVirtualNetworkRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRule_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) + AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec(generators) + serversVirtualNetworkRule_SpecGenerator = gen.Struct(reflect.TypeOf(ServersVirtualNetworkRule_Spec{}), generators) + return serversVirtualNetworkRule_SpecGenerator } @@ -207,3 +271,8 @@ func AddIndependentPropertyGeneratorsForServersVirtualNetworkRule_Spec(gens map[ gens["IgnoreMissingVnetServiceEndpoint"] = gen.PtrOf(gen.Bool()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForServersVirtualNetworkRule_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersVirtualNetworkRuleOperatorSpecGenerator()) +} diff --git a/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen.go b/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen.go index 7d357db0c3e..15e7b3bc2ba 100644 --- a/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen.go +++ b/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (assessment *ServersVulnerabilityAssessment) SetConditions(conditions condi assessment.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServersVulnerabilityAssessment{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (assessment *ServersVulnerabilityAssessment) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServersVulnerabilityAssessment{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (assessment *ServersVulnerabilityAssessment) SecretDestinationExpressions() []*core.DestinationExpression { + if assessment.Spec.OperatorSpec == nil { + return nil + } + return assessment.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServersVulnerabilityAssessment{} // AzureName returns the Azure name of the resource (always "default") @@ -140,7 +163,8 @@ type ServersVulnerabilityAssessmentList struct { // Storage version of v1api20211101.ServersVulnerabilityAssessment_Spec type ServersVulnerabilityAssessment_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *ServersVulnerabilityAssessmentOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -206,6 +230,14 @@ func (assessment *ServersVulnerabilityAssessment_STATUS) ConvertStatusTo(destina return destination.ConvertStatusFrom(assessment) } +// Storage version of v1api20211101.ServersVulnerabilityAssessmentOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServersVulnerabilityAssessmentOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&ServersVulnerabilityAssessment{}, &ServersVulnerabilityAssessmentList{}) } diff --git a/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen_test.go b/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen_test.go index 584e05d072f..44ae2d6123c 100644 --- a/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen_test.go +++ b/v2/api/sql/v1api20211101/storage/servers_vulnerability_assessment_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment(gens map[stri gens["Status"] = ServersVulnerabilityAssessment_STATUSGenerator() } +func Test_ServersVulnerabilityAssessmentOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServersVulnerabilityAssessmentOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec, ServersVulnerabilityAssessmentOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec runs a test to see if a specific instance of ServersVulnerabilityAssessmentOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServersVulnerabilityAssessmentOperatorSpec(subject ServersVulnerabilityAssessmentOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServersVulnerabilityAssessmentOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServersVulnerabilityAssessmentOperatorSpec instances for property testing - lazily instantiated by +// ServersVulnerabilityAssessmentOperatorSpecGenerator() +var serversVulnerabilityAssessmentOperatorSpecGenerator gopter.Gen + +// ServersVulnerabilityAssessmentOperatorSpecGenerator returns a generator of ServersVulnerabilityAssessmentOperatorSpec instances for property testing. +func ServersVulnerabilityAssessmentOperatorSpecGenerator() gopter.Gen { + if serversVulnerabilityAssessmentOperatorSpecGenerator != nil { + return serversVulnerabilityAssessmentOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serversVulnerabilityAssessmentOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServersVulnerabilityAssessmentOperatorSpec{}), generators) + + return serversVulnerabilityAssessmentOperatorSpecGenerator +} + func Test_ServersVulnerabilityAssessment_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -230,5 +285,6 @@ func AddIndependentPropertyGeneratorsForServersVulnerabilityAssessment_Spec(gens // AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForServersVulnerabilityAssessment_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(ServersVulnerabilityAssessmentOperatorSpecGenerator()) gens["RecurringScans"] = gen.PtrOf(VulnerabilityAssessmentRecurringScansPropertiesGenerator()) } diff --git a/v2/api/sql/v1api20211101/storage/structure.txt b/v2/api/sql/v1api20211101/storage/structure.txt index 7916bddf944..f4f7a1a2b5a 100644 --- a/v2/api/sql/v1api20211101/storage/structure.txt +++ b/v2/api/sql/v1api20211101/storage/structure.txt @@ -27,11 +27,13 @@ Server: Resource │ ├── KeyId: *string │ ├── Location: *string │ ├── MinimalTlsVersion: *string -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (2 properties) │ │ │ ├── FullyQualifiedDomainName: *genruntime.ConfigMapDestination │ │ │ └── PropertyBag: genruntime.PropertyBag -│ │ └── PropertyBag: genruntime.PropertyBag +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrimaryUserAssignedIdentityReference: *genruntime.ResourceReference @@ -94,9 +96,13 @@ Server: Resource └── WorkspaceFeature: *string ServersAdministrator: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AdministratorType: *string │ ├── Login: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -117,7 +123,11 @@ ServersAdministrator: Resource └── Type: *string ServersAdvancedThreatProtectionSetting: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -140,12 +150,16 @@ ServersAdvancedThreatProtectionSetting: Resource └── Type: *string ServersAuditingSetting: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AuditActionsAndGroups: string[] │ ├── IsAzureMonitorTargetEnabled: *bool │ ├── IsDevopsAuditEnabled: *bool │ ├── IsManagedIdentityInUse: *bool │ ├── IsStorageSecondaryKeyInUse: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -173,8 +187,12 @@ ServersAuditingSetting: Resource └── Type: *string ServersAzureADOnlyAuthentication: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureADOnlyAuthentication: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -187,8 +205,12 @@ ServersAzureADOnlyAuthentication: Resource └── Type: *string ServersConnectionPolicy: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── ConnectionType: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -203,7 +225,7 @@ ServersConnectionPolicy: Resource └── Type: *string ServersDatabase: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (33 properties) +├── Spec: Object (34 properties) │ ├── AutoPauseDelay: *int │ ├── AzureName: string │ ├── CatalogCollation: *string @@ -225,6 +247,10 @@ ServersDatabase: Resource │ ├── MaintenanceConfigurationId: *string │ ├── MaxSizeBytes: *int │ ├── MinCapacity: *float64 +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -320,7 +346,11 @@ ServersDatabase: Resource └── ZoneRedundant: *bool ServersDatabasesAdvancedThreatProtectionSetting: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -343,11 +373,15 @@ ServersDatabasesAdvancedThreatProtectionSetting: Resource └── Type: *string ServersDatabasesAuditingSetting: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (13 properties) +├── Spec: Object (14 properties) │ ├── AuditActionsAndGroups: string[] │ ├── IsAzureMonitorTargetEnabled: *bool │ ├── IsManagedIdentityInUse: *bool │ ├── IsStorageSecondaryKeyInUse: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -375,8 +409,12 @@ ServersDatabasesAuditingSetting: Resource └── Type: *string ServersDatabasesBackupLongTermRetentionPolicy: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── MonthlyRetention: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -395,8 +433,12 @@ ServersDatabasesBackupLongTermRetentionPolicy: Resource └── YearlyRetention: *string ServersDatabasesBackupShortTermRetentionPolicy: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── DiffBackupIntervalInHours: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -411,10 +453,14 @@ ServersDatabasesBackupShortTermRetentionPolicy: Resource └── Type: *string ServersDatabasesSecurityAlertPolicy: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── DisabledAlerts: string[] │ ├── EmailAccountAdmins: *bool │ ├── EmailAddresses: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -445,7 +491,11 @@ ServersDatabasesSecurityAlertPolicy: Resource └── Type: *string ServersDatabasesTransparentDataEncryption: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -459,7 +509,11 @@ ServersDatabasesTransparentDataEncryption: Resource └── Type: *string ServersDatabasesVulnerabilityAssessment: Resource ├── Owner: sql/v1api20211101.ServersDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -486,7 +540,7 @@ ServersDatabasesVulnerabilityAssessment: Resource └── Type: *string ServersElasticPool: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (14 properties) +├── Spec: Object (15 properties) │ ├── AzureName: string │ ├── HighAvailabilityReplicaCount: *int │ ├── LicenseType: *string @@ -494,6 +548,10 @@ ServersElasticPool: Resource │ ├── MaintenanceConfigurationId: *string │ ├── MaxSizeBytes: *int │ ├── MinCapacity: *float64 +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PerDatabaseSettings: *Object (3 properties) @@ -540,9 +598,13 @@ ServersElasticPool: Resource └── ZoneRedundant: *bool ServersFailoverGroup: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── DatabasesReferences: genruntime.ResourceReference[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PartnerServers: Object (2 properties)[] @@ -582,9 +644,13 @@ ServersFailoverGroup: Resource └── Type: *string ServersFirewallRule: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -599,9 +665,13 @@ ServersFirewallRule: Resource └── Type: *string ServersIPV6FirewallRule: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── EndIPv6Address: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -616,8 +686,12 @@ ServersIPV6FirewallRule: Resource └── Type: *string ServersOutboundFirewallRule: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -630,10 +704,14 @@ ServersOutboundFirewallRule: Resource └── Type: *string ServersSecurityAlertPolicy: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── DisabledAlerts: string[] │ ├── EmailAccountAdmins: *bool │ ├── EmailAddresses: string[] +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -664,9 +742,13 @@ ServersSecurityAlertPolicy: Resource └── Type: *string ServersVirtualNetworkRule: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── AzureName: string │ ├── IgnoreMissingVnetServiceEndpoint: *bool +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -682,7 +764,11 @@ ServersVirtualNetworkRule: Resource └── VirtualNetworkSubnetId: *string ServersVulnerabilityAssessment: Resource ├── Owner: sql/v1api20211101.Server -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/sql/v1api20211101/storage/zz_generated.deepcopy.go b/v2/api/sql/v1api20211101/storage/zz_generated.deepcopy.go index 60130c7f408..05f1dd1e11a 100644 --- a/v2/api/sql/v1api20211101/storage/zz_generated.deepcopy.go +++ b/v2/api/sql/v1api20211101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -743,6 +744,17 @@ func (in *ServerOperatorConfigMaps) DeepCopy() *ServerOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ServerOperatorConfigMaps) @@ -755,6 +767,17 @@ func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerOperatorSpec. @@ -1090,6 +1113,50 @@ func (in *ServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAdministratorOperatorSpec) DeepCopyInto(out *ServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAdministratorOperatorSpec. +func (in *ServersAdministratorOperatorSpec) DeepCopy() *ServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdministrator_STATUS) DeepCopyInto(out *ServersAdministrator_STATUS) { *out = *in @@ -1172,6 +1239,11 @@ func (in *ServersAdministrator_Spec) DeepCopyInto(out *ServersAdministrator_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1275,6 +1347,50 @@ func (in *ServersAdvancedThreatProtectionSettingList) DeepCopyObject() runtime.O return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAdvancedThreatProtectionSettingOperatorSpec) DeepCopyInto(out *ServersAdvancedThreatProtectionSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAdvancedThreatProtectionSettingOperatorSpec. +func (in *ServersAdvancedThreatProtectionSettingOperatorSpec) DeepCopy() *ServersAdvancedThreatProtectionSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAdvancedThreatProtectionSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdvancedThreatProtectionSetting_STATUS) DeepCopyInto(out *ServersAdvancedThreatProtectionSetting_STATUS) { *out = *in @@ -1337,6 +1453,11 @@ func (in *ServersAdvancedThreatProtectionSetting_STATUS) DeepCopy() *ServersAdva // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdvancedThreatProtectionSetting_Spec) DeepCopyInto(out *ServersAdvancedThreatProtectionSetting_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAdvancedThreatProtectionSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1425,6 +1546,50 @@ func (in *ServersAuditingSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAuditingSettingOperatorSpec) DeepCopyInto(out *ServersAuditingSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAuditingSettingOperatorSpec. +func (in *ServersAuditingSettingOperatorSpec) DeepCopy() *ServersAuditingSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAuditingSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAuditingSetting_STATUS) DeepCopyInto(out *ServersAuditingSetting_STATUS) { *out = *in @@ -1547,6 +1712,11 @@ func (in *ServersAuditingSetting_Spec) DeepCopyInto(out *ServersAuditingSetting_ *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAuditingSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1660,6 +1830,50 @@ func (in *ServersAzureADOnlyAuthenticationList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAzureADOnlyAuthenticationOperatorSpec) DeepCopyInto(out *ServersAzureADOnlyAuthenticationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAzureADOnlyAuthenticationOperatorSpec. +func (in *ServersAzureADOnlyAuthenticationOperatorSpec) DeepCopy() *ServersAzureADOnlyAuthenticationOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAzureADOnlyAuthenticationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAzureADOnlyAuthentication_STATUS) DeepCopyInto(out *ServersAzureADOnlyAuthentication_STATUS) { *out = *in @@ -1717,6 +1931,11 @@ func (in *ServersAzureADOnlyAuthentication_Spec) DeepCopyInto(out *ServersAzureA *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAzureADOnlyAuthenticationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1800,6 +2019,50 @@ func (in *ServersConnectionPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersConnectionPolicyOperatorSpec) DeepCopyInto(out *ServersConnectionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersConnectionPolicyOperatorSpec. +func (in *ServersConnectionPolicyOperatorSpec) DeepCopy() *ServersConnectionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersConnectionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersConnectionPolicy_STATUS) DeepCopyInto(out *ServersConnectionPolicy_STATUS) { *out = *in @@ -1867,6 +2130,11 @@ func (in *ServersConnectionPolicy_Spec) DeepCopyInto(out *ServersConnectionPolic *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersConnectionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1950,6 +2218,50 @@ func (in *ServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabaseOperatorSpec) DeepCopyInto(out *ServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabaseOperatorSpec. +func (in *ServersDatabaseOperatorSpec) DeepCopy() *ServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabase_STATUS) DeepCopyInto(out *ServersDatabase_STATUS) { *out = *in @@ -2299,6 +2611,11 @@ func (in *ServersDatabase_Spec) DeepCopyInto(out *ServersDatabase_Spec) { *out = new(float64) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2454,6 +2771,50 @@ func (in *ServersDatabasesAdvancedThreatProtectionSettingList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec. +func (in *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) DeepCopy() *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) { *out = *in @@ -2516,6 +2877,11 @@ func (in *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) DeepCopy() *Se // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAdvancedThreatProtectionSetting_Spec) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSetting_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2604,6 +2970,50 @@ func (in *ServersDatabasesAuditingSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesAuditingSettingOperatorSpec) DeepCopyInto(out *ServersDatabasesAuditingSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesAuditingSettingOperatorSpec. +func (in *ServersDatabasesAuditingSettingOperatorSpec) DeepCopy() *ServersDatabasesAuditingSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesAuditingSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAuditingSetting_STATUS) DeepCopyInto(out *ServersDatabasesAuditingSetting_STATUS) { *out = *in @@ -2721,6 +3131,11 @@ func (in *ServersDatabasesAuditingSetting_Spec) DeepCopyInto(out *ServersDatabas *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesAuditingSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2834,6 +3249,50 @@ func (in *ServersDatabasesBackupLongTermRetentionPolicyList) DeepCopyObject() ru return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec. +func (in *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) DeepCopy() *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) DeepCopyInto(out *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) { *out = *in @@ -2906,8 +3365,13 @@ func (in *ServersDatabasesBackupLongTermRetentionPolicy_Spec) DeepCopyInto(out * *out = new(string) **out = **in } - if in.Owner != nil { - in, out := &in.Owner, &out.Owner + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } + if in.Owner != nil { + in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) **out = **in } @@ -3004,6 +3468,50 @@ func (in *ServersDatabasesBackupShortTermRetentionPolicyList) DeepCopyObject() r return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec. +func (in *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) DeepCopy() *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesBackupShortTermRetentionPolicy_STATUS) DeepCopyInto(out *ServersDatabasesBackupShortTermRetentionPolicy_STATUS) { *out = *in @@ -3066,6 +3574,11 @@ func (in *ServersDatabasesBackupShortTermRetentionPolicy_Spec) DeepCopyInto(out *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3154,6 +3667,50 @@ func (in *ServersDatabasesSecurityAlertPolicyList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesSecurityAlertPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesSecurityAlertPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesSecurityAlertPolicyOperatorSpec. +func (in *ServersDatabasesSecurityAlertPolicyOperatorSpec) DeepCopy() *ServersDatabasesSecurityAlertPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesSecurityAlertPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesSecurityAlertPolicy_STATUS) DeepCopyInto(out *ServersDatabasesSecurityAlertPolicy_STATUS) { *out = *in @@ -3256,6 +3813,11 @@ func (in *ServersDatabasesSecurityAlertPolicy_Spec) DeepCopyInto(out *ServersDat *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesSecurityAlertPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3359,6 +3921,50 @@ func (in *ServersDatabasesTransparentDataEncryptionList) DeepCopyObject() runtim return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesTransparentDataEncryptionOperatorSpec) DeepCopyInto(out *ServersDatabasesTransparentDataEncryptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesTransparentDataEncryptionOperatorSpec. +func (in *ServersDatabasesTransparentDataEncryptionOperatorSpec) DeepCopy() *ServersDatabasesTransparentDataEncryptionOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesTransparentDataEncryptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesTransparentDataEncryption_STATUS) DeepCopyInto(out *ServersDatabasesTransparentDataEncryption_STATUS) { *out = *in @@ -3411,6 +4017,11 @@ func (in *ServersDatabasesTransparentDataEncryption_STATUS) DeepCopy() *ServersD // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesTransparentDataEncryption_Spec) DeepCopyInto(out *ServersDatabasesTransparentDataEncryption_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesTransparentDataEncryptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3499,6 +4110,50 @@ func (in *ServersDatabasesVulnerabilityAssessmentList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesVulnerabilityAssessmentOperatorSpec) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesVulnerabilityAssessmentOperatorSpec. +func (in *ServersDatabasesVulnerabilityAssessmentOperatorSpec) DeepCopy() *ServersDatabasesVulnerabilityAssessmentOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesVulnerabilityAssessmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesVulnerabilityAssessment_STATUS) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessment_STATUS) { *out = *in @@ -3556,6 +4211,11 @@ func (in *ServersDatabasesVulnerabilityAssessment_STATUS) DeepCopy() *ServersDat // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesVulnerabilityAssessment_Spec) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesVulnerabilityAssessmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3664,6 +4324,50 @@ func (in *ServersElasticPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersElasticPoolOperatorSpec) DeepCopyInto(out *ServersElasticPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersElasticPoolOperatorSpec. +func (in *ServersElasticPoolOperatorSpec) DeepCopy() *ServersElasticPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ServersElasticPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersElasticPool_STATUS) DeepCopyInto(out *ServersElasticPool_STATUS) { *out = *in @@ -3808,6 +4512,11 @@ func (in *ServersElasticPool_Spec) DeepCopyInto(out *ServersElasticPool_Spec) { *out = new(float64) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersElasticPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3913,6 +4622,50 @@ func (in *ServersFailoverGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersFailoverGroupOperatorSpec) DeepCopyInto(out *ServersFailoverGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersFailoverGroupOperatorSpec. +func (in *ServersFailoverGroupOperatorSpec) DeepCopy() *ServersFailoverGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ServersFailoverGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersFailoverGroup_STATUS) DeepCopyInto(out *ServersFailoverGroup_STATUS) { *out = *in @@ -4009,6 +4762,11 @@ func (in *ServersFailoverGroup_Spec) DeepCopyInto(out *ServersFailoverGroup_Spec *out = make([]genruntime.ResourceReference, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersFailoverGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4116,6 +4874,50 @@ func (in *ServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersFirewallRuleOperatorSpec) DeepCopyInto(out *ServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersFirewallRuleOperatorSpec. +func (in *ServersFirewallRuleOperatorSpec) DeepCopy() *ServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersFirewallRule_STATUS) DeepCopyInto(out *ServersFirewallRule_STATUS) { *out = *in @@ -4178,6 +4980,11 @@ func (in *ServersFirewallRule_Spec) DeepCopyInto(out *ServersFirewallRule_Spec) *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4266,6 +5073,50 @@ func (in *ServersIPV6FirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersIPV6FirewallRuleOperatorSpec) DeepCopyInto(out *ServersIPV6FirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersIPV6FirewallRuleOperatorSpec. +func (in *ServersIPV6FirewallRuleOperatorSpec) DeepCopy() *ServersIPV6FirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersIPV6FirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersIPV6FirewallRule_STATUS) DeepCopyInto(out *ServersIPV6FirewallRule_STATUS) { *out = *in @@ -4328,6 +5179,11 @@ func (in *ServersIPV6FirewallRule_Spec) DeepCopyInto(out *ServersIPV6FirewallRul *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersIPV6FirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4416,6 +5272,50 @@ func (in *ServersOutboundFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersOutboundFirewallRuleOperatorSpec) DeepCopyInto(out *ServersOutboundFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersOutboundFirewallRuleOperatorSpec. +func (in *ServersOutboundFirewallRuleOperatorSpec) DeepCopy() *ServersOutboundFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersOutboundFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersOutboundFirewallRule_STATUS) DeepCopyInto(out *ServersOutboundFirewallRule_STATUS) { *out = *in @@ -4468,6 +5368,11 @@ func (in *ServersOutboundFirewallRule_STATUS) DeepCopy() *ServersOutboundFirewal // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersOutboundFirewallRule_Spec) DeepCopyInto(out *ServersOutboundFirewallRule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersOutboundFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4551,6 +5456,50 @@ func (in *ServersSecurityAlertPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersSecurityAlertPolicyOperatorSpec) DeepCopyInto(out *ServersSecurityAlertPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersSecurityAlertPolicyOperatorSpec. +func (in *ServersSecurityAlertPolicyOperatorSpec) DeepCopy() *ServersSecurityAlertPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersSecurityAlertPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersSecurityAlertPolicy_STATUS) DeepCopyInto(out *ServersSecurityAlertPolicy_STATUS) { *out = *in @@ -4653,6 +5602,11 @@ func (in *ServersSecurityAlertPolicy_Spec) DeepCopyInto(out *ServersSecurityAler *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersSecurityAlertPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4756,6 +5710,50 @@ func (in *ServersVirtualNetworkRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersVirtualNetworkRuleOperatorSpec) DeepCopyInto(out *ServersVirtualNetworkRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersVirtualNetworkRuleOperatorSpec. +func (in *ServersVirtualNetworkRuleOperatorSpec) DeepCopy() *ServersVirtualNetworkRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersVirtualNetworkRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVirtualNetworkRule_STATUS) DeepCopyInto(out *ServersVirtualNetworkRule_STATUS) { *out = *in @@ -4823,6 +5821,11 @@ func (in *ServersVirtualNetworkRule_Spec) DeepCopyInto(out *ServersVirtualNetwor *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersVirtualNetworkRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4911,6 +5914,50 @@ func (in *ServersVulnerabilityAssessmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersVulnerabilityAssessmentOperatorSpec) DeepCopyInto(out *ServersVulnerabilityAssessmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersVulnerabilityAssessmentOperatorSpec. +func (in *ServersVulnerabilityAssessmentOperatorSpec) DeepCopy() *ServersVulnerabilityAssessmentOperatorSpec { + if in == nil { + return nil + } + out := new(ServersVulnerabilityAssessmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVulnerabilityAssessment_STATUS) DeepCopyInto(out *ServersVulnerabilityAssessment_STATUS) { *out = *in @@ -4968,6 +6015,11 @@ func (in *ServersVulnerabilityAssessment_STATUS) DeepCopy() *ServersVulnerabilit // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVulnerabilityAssessment_Spec) DeepCopyInto(out *ServersVulnerabilityAssessment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersVulnerabilityAssessmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/sql/v1api20211101/structure.txt b/v2/api/sql/v1api20211101/structure.txt index 3a7c9f1c030..2be0d8e3063 100644 --- a/v2/api/sql/v1api20211101/structure.txt +++ b/v2/api/sql/v1api20211101/structure.txt @@ -35,9 +35,11 @@ Server: Resource │ ├── KeyId: *string │ ├── Location: *string │ ├── MinimalTlsVersion: *string -│ ├── OperatorSpec: *Object (1 property) -│ │ └── ConfigMaps: *Object (1 property) -│ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── ConfigMaps: *Object (1 property) +│ │ │ └── FullyQualifiedDomainName: *genruntime.ConfigMapDestination +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PrimaryUserAssignedIdentityReference: *genruntime.ResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) @@ -118,10 +120,13 @@ Server: Resource └── "Disconnected" ServersAdministrator: Resource ├── Owner: Server -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AdministratorType: *Enum (1 value) │ │ └── "ActiveDirectory" │ ├── Login: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── Sid: Validated<*string> (1 rule) │ │ └── Rule 0: Pattern: "^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$" @@ -142,7 +147,10 @@ ServersAdministrator: Resource └── Type: *string ServersAdvancedThreatProtectionSetting: Resource ├── Owner: Server -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── State: *Enum (3 values) │ ├── "Disabled" @@ -175,12 +183,15 @@ ServersAdvancedThreatProtectionSetting: Resource └── Type: *string ServersAuditingSetting: Resource ├── Owner: Server -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AuditActionsAndGroups: string[] │ ├── IsAzureMonitorTargetEnabled: *bool │ ├── IsDevopsAuditEnabled: *bool │ ├── IsManagedIdentityInUse: *bool │ ├── IsStorageSecondaryKeyInUse: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── QueueDelayMs: *int │ ├── RetentionDays: *int @@ -210,8 +221,11 @@ ServersAuditingSetting: Resource └── Type: *string ServersAzureADOnlyAuthentication: Resource ├── Owner: Server -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureADOnlyAuthentication: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── AzureADOnlyAuthentication: *bool @@ -221,11 +235,14 @@ ServersAzureADOnlyAuthentication: Resource └── Type: *string ServersConnectionPolicy: Resource ├── Owner: Server -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── ConnectionType: *Enum (3 values) │ │ ├── "Default" │ │ ├── "Proxy" │ │ └── "Redirect" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (7 properties) ├── Conditions: conditions.Condition[] @@ -240,7 +257,7 @@ ServersConnectionPolicy: Resource └── Type: *string ServersDatabase: Resource ├── Owner: Server -├── Spec: Object (31 properties) +├── Spec: Object (32 properties) │ ├── AutoPauseDelay: *int │ ├── AzureName: string │ ├── CatalogCollation: *Enum (2 values) @@ -277,6 +294,9 @@ ServersDatabase: Resource │ ├── MaintenanceConfigurationId: *string │ ├── MaxSizeBytes: *int │ ├── MinCapacity: *float64 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ReadScale: *Enum (2 values) │ │ ├── "Disabled" @@ -430,7 +450,10 @@ ServersDatabase: Resource └── ZoneRedundant: *bool ServersDatabasesAdvancedThreatProtectionSetting: Resource ├── Owner: ServersDatabase -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── State: *Enum (3 values) │ ├── "Disabled" @@ -463,11 +486,14 @@ ServersDatabasesAdvancedThreatProtectionSetting: Resource └── Type: *string ServersDatabasesAuditingSetting: Resource ├── Owner: ServersDatabase -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AuditActionsAndGroups: string[] │ ├── IsAzureMonitorTargetEnabled: *bool │ ├── IsManagedIdentityInUse: *bool │ ├── IsStorageSecondaryKeyInUse: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── QueueDelayMs: *int │ ├── RetentionDays: *int @@ -497,8 +523,11 @@ ServersDatabasesAuditingSetting: Resource └── Type: *string ServersDatabasesBackupLongTermRetentionPolicy: Resource ├── Owner: ServersDatabase -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── MonthlyRetention: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── WeekOfYear: *int │ ├── WeeklyRetention: *string @@ -514,10 +543,13 @@ ServersDatabasesBackupLongTermRetentionPolicy: Resource └── YearlyRetention: *string ServersDatabasesBackupShortTermRetentionPolicy: Resource ├── Owner: ServersDatabase -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── DiffBackupIntervalInHours: *Enum (2 values) │ │ ├── 12 │ │ └── 24 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RetentionDays: *int └── Status: Object (6 properties) @@ -531,10 +563,13 @@ ServersDatabasesBackupShortTermRetentionPolicy: Resource └── Type: *string ServersDatabasesSecurityAlertPolicy: Resource ├── Owner: ServersDatabase -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── DisabledAlerts: string[] │ ├── EmailAccountAdmins: *bool │ ├── EmailAddresses: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RetentionDays: *int │ ├── State: *Enum (2 values) @@ -573,7 +608,10 @@ ServersDatabasesSecurityAlertPolicy: Resource └── Type: *string ServersDatabasesTransparentDataEncryption: Resource ├── Owner: ServersDatabase -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── State: *Enum (2 values) │ ├── "Disabled" @@ -588,7 +626,10 @@ ServersDatabasesTransparentDataEncryption: Resource └── Type: *string ServersDatabasesVulnerabilityAssessment: Resource ├── Owner: ServersDatabase -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RecurringScans: *Object (3 properties) │ │ ├── EmailSubscriptionAdmins: *bool @@ -610,7 +651,7 @@ ServersDatabasesVulnerabilityAssessment: Resource └── Type: *string ServersElasticPool: Resource ├── Owner: Server -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AzureName: string │ ├── HighAvailabilityReplicaCount: *int │ ├── LicenseType: *Enum (2 values) @@ -620,6 +661,9 @@ ServersElasticPool: Resource │ ├── MaintenanceConfigurationId: *string │ ├── MaxSizeBytes: *int │ ├── MinCapacity: *float64 +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PerDatabaseSettings: *Object (2 properties) │ │ ├── MaxCapacity: *float64 @@ -664,9 +708,12 @@ ServersElasticPool: Resource └── ZoneRedundant: *bool ServersFailoverGroup: Resource ├── Owner: Server -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: string │ ├── DatabasesReferences: genruntime.ResourceReference[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PartnerServers: Object (1 property)[] │ │ └── Reference: *genruntime.ResourceReference @@ -709,9 +756,12 @@ ServersFailoverGroup: Resource └── Type: *string ServersFirewallRule: Resource ├── Owner: Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIpAddress: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIpAddress: *string └── Status: Object (6 properties) @@ -723,9 +773,12 @@ ServersFirewallRule: Resource └── Type: *string ServersIPV6FirewallRule: Resource ├── Owner: Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── EndIPv6Address: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── StartIPv6Address: *string └── Status: Object (6 properties) @@ -737,8 +790,11 @@ ServersIPV6FirewallRule: Resource └── Type: *string ServersOutboundFirewallRule: Resource ├── Owner: Server -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -748,10 +804,13 @@ ServersOutboundFirewallRule: Resource └── Type: *string ServersSecurityAlertPolicy: Resource ├── Owner: Server -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── DisabledAlerts: string[] │ ├── EmailAccountAdmins: *bool │ ├── EmailAddresses: string[] +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RetentionDays: *int │ ├── State: *Enum (2 values) @@ -790,9 +849,12 @@ ServersSecurityAlertPolicy: Resource └── Type: *string ServersVirtualNetworkRule: Resource ├── Owner: Server -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string │ ├── IgnoreMissingVnetServiceEndpoint: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── VirtualNetworkSubnetReference: *genruntime.ResourceReference └── Status: Object (7 properties) @@ -811,7 +873,10 @@ ServersVirtualNetworkRule: Resource └── VirtualNetworkSubnetId: *string ServersVulnerabilityAssessment: Resource ├── Owner: Server -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RecurringScans: *Object (3 properties) │ │ ├── EmailSubscriptionAdmins: *bool diff --git a/v2/api/sql/v1api20211101/zz_generated.deepcopy.go b/v2/api/sql/v1api20211101/zz_generated.deepcopy.go index bda0fee9a7d..010418ccbb9 100644 --- a/v2/api/sql/v1api20211101/zz_generated.deepcopy.go +++ b/v2/api/sql/v1api20211101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20211101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -606,11 +607,33 @@ func (in *ServerOperatorConfigMaps) DeepCopy() *ServerOperatorConfigMaps { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerOperatorSpec) DeepCopyInto(out *ServerOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(ServerOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerOperatorSpec. @@ -925,6 +948,43 @@ func (in *ServersAdministratorList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAdministratorOperatorSpec) DeepCopyInto(out *ServersAdministratorOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAdministratorOperatorSpec. +func (in *ServersAdministratorOperatorSpec) DeepCopy() *ServersAdministratorOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAdministratorOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdministrator_STATUS) DeepCopyInto(out *ServersAdministrator_STATUS) { *out = *in @@ -1000,6 +1060,11 @@ func (in *ServersAdministrator_Spec) DeepCopyInto(out *ServersAdministrator_Spec *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAdministratorOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1096,6 +1161,43 @@ func (in *ServersAdvancedThreatProtectionSettingList) DeepCopyObject() runtime.O return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAdvancedThreatProtectionSettingOperatorSpec) DeepCopyInto(out *ServersAdvancedThreatProtectionSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAdvancedThreatProtectionSettingOperatorSpec. +func (in *ServersAdvancedThreatProtectionSettingOperatorSpec) DeepCopy() *ServersAdvancedThreatProtectionSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAdvancedThreatProtectionSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdvancedThreatProtectionSetting_STATUS) DeepCopyInto(out *ServersAdvancedThreatProtectionSetting_STATUS) { *out = *in @@ -1151,6 +1253,11 @@ func (in *ServersAdvancedThreatProtectionSetting_STATUS) DeepCopy() *ServersAdva // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAdvancedThreatProtectionSetting_Spec) DeepCopyInto(out *ServersAdvancedThreatProtectionSetting_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAdvancedThreatProtectionSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1232,6 +1339,43 @@ func (in *ServersAuditingSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAuditingSettingOperatorSpec) DeepCopyInto(out *ServersAuditingSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAuditingSettingOperatorSpec. +func (in *ServersAuditingSettingOperatorSpec) DeepCopy() *ServersAuditingSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAuditingSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAuditingSetting_STATUS) DeepCopyInto(out *ServersAuditingSetting_STATUS) { *out = *in @@ -1347,6 +1491,11 @@ func (in *ServersAuditingSetting_Spec) DeepCopyInto(out *ServersAuditingSetting_ *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAuditingSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1453,6 +1602,43 @@ func (in *ServersAzureADOnlyAuthenticationList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersAzureADOnlyAuthenticationOperatorSpec) DeepCopyInto(out *ServersAzureADOnlyAuthenticationOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersAzureADOnlyAuthenticationOperatorSpec. +func (in *ServersAzureADOnlyAuthenticationOperatorSpec) DeepCopy() *ServersAzureADOnlyAuthenticationOperatorSpec { + if in == nil { + return nil + } + out := new(ServersAzureADOnlyAuthenticationOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersAzureADOnlyAuthentication_STATUS) DeepCopyInto(out *ServersAzureADOnlyAuthentication_STATUS) { *out = *in @@ -1503,6 +1689,11 @@ func (in *ServersAzureADOnlyAuthentication_Spec) DeepCopyInto(out *ServersAzureA *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersAzureADOnlyAuthenticationOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1579,6 +1770,43 @@ func (in *ServersConnectionPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersConnectionPolicyOperatorSpec) DeepCopyInto(out *ServersConnectionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersConnectionPolicyOperatorSpec. +func (in *ServersConnectionPolicyOperatorSpec) DeepCopy() *ServersConnectionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersConnectionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersConnectionPolicy_STATUS) DeepCopyInto(out *ServersConnectionPolicy_STATUS) { *out = *in @@ -1639,6 +1867,11 @@ func (in *ServersConnectionPolicy_Spec) DeepCopyInto(out *ServersConnectionPolic *out = new(ServerConnectionPolicyProperties_ConnectionType) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersConnectionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1715,6 +1948,43 @@ func (in *ServersDatabaseList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabaseOperatorSpec) DeepCopyInto(out *ServersDatabaseOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabaseOperatorSpec. +func (in *ServersDatabaseOperatorSpec) DeepCopy() *ServersDatabaseOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabaseOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabase_STATUS) DeepCopyInto(out *ServersDatabase_STATUS) { *out = *in @@ -2057,6 +2327,11 @@ func (in *ServersDatabase_Spec) DeepCopyInto(out *ServersDatabase_Spec) { *out = new(float64) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabaseOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2205,6 +2480,43 @@ func (in *ServersDatabasesAdvancedThreatProtectionSettingList) DeepCopyObject() return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec. +func (in *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) DeepCopy() *ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) { *out = *in @@ -2260,6 +2572,11 @@ func (in *ServersDatabasesAdvancedThreatProtectionSetting_STATUS) DeepCopy() *Se // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAdvancedThreatProtectionSetting_Spec) DeepCopyInto(out *ServersDatabasesAdvancedThreatProtectionSetting_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesAdvancedThreatProtectionSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2341,6 +2658,43 @@ func (in *ServersDatabasesAuditingSettingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesAuditingSettingOperatorSpec) DeepCopyInto(out *ServersDatabasesAuditingSettingOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesAuditingSettingOperatorSpec. +func (in *ServersDatabasesAuditingSettingOperatorSpec) DeepCopy() *ServersDatabasesAuditingSettingOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesAuditingSettingOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesAuditingSetting_STATUS) DeepCopyInto(out *ServersDatabasesAuditingSetting_STATUS) { *out = *in @@ -2451,6 +2805,11 @@ func (in *ServersDatabasesAuditingSetting_Spec) DeepCopyInto(out *ServersDatabas *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesAuditingSettingOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2557,6 +2916,43 @@ func (in *ServersDatabasesBackupLongTermRetentionPolicyList) DeepCopyObject() ru return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec. +func (in *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) DeepCopy() *ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) DeepCopyInto(out *ServersDatabasesBackupLongTermRetentionPolicy_STATUS) { *out = *in @@ -2622,6 +3018,11 @@ func (in *ServersDatabasesBackupLongTermRetentionPolicy_Spec) DeepCopyInto(out * *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesBackupLongTermRetentionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2713,6 +3114,43 @@ func (in *ServersDatabasesBackupShortTermRetentionPolicyList) DeepCopyObject() r return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec. +func (in *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) DeepCopy() *ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesBackupShortTermRetentionPolicy_STATUS) DeepCopyInto(out *ServersDatabasesBackupShortTermRetentionPolicy_STATUS) { *out = *in @@ -2768,6 +3206,11 @@ func (in *ServersDatabasesBackupShortTermRetentionPolicy_Spec) DeepCopyInto(out *out = new(BackupShortTermRetentionPolicyProperties_DiffBackupIntervalInHours) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesBackupShortTermRetentionPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2849,6 +3292,43 @@ func (in *ServersDatabasesSecurityAlertPolicyList) DeepCopyObject() runtime.Obje return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesSecurityAlertPolicyOperatorSpec) DeepCopyInto(out *ServersDatabasesSecurityAlertPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesSecurityAlertPolicyOperatorSpec. +func (in *ServersDatabasesSecurityAlertPolicyOperatorSpec) DeepCopy() *ServersDatabasesSecurityAlertPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesSecurityAlertPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesSecurityAlertPolicy_STATUS) DeepCopyInto(out *ServersDatabasesSecurityAlertPolicy_STATUS) { *out = *in @@ -2944,6 +3424,11 @@ func (in *ServersDatabasesSecurityAlertPolicy_Spec) DeepCopyInto(out *ServersDat *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesSecurityAlertPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3040,6 +3525,43 @@ func (in *ServersDatabasesTransparentDataEncryptionList) DeepCopyObject() runtim return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesTransparentDataEncryptionOperatorSpec) DeepCopyInto(out *ServersDatabasesTransparentDataEncryptionOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesTransparentDataEncryptionOperatorSpec. +func (in *ServersDatabasesTransparentDataEncryptionOperatorSpec) DeepCopy() *ServersDatabasesTransparentDataEncryptionOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesTransparentDataEncryptionOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesTransparentDataEncryption_STATUS) DeepCopyInto(out *ServersDatabasesTransparentDataEncryption_STATUS) { *out = *in @@ -3085,6 +3607,11 @@ func (in *ServersDatabasesTransparentDataEncryption_STATUS) DeepCopy() *ServersD // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesTransparentDataEncryption_Spec) DeepCopyInto(out *ServersDatabasesTransparentDataEncryption_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesTransparentDataEncryptionOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3166,6 +3693,43 @@ func (in *ServersDatabasesVulnerabilityAssessmentList) DeepCopyObject() runtime. return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersDatabasesVulnerabilityAssessmentOperatorSpec) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersDatabasesVulnerabilityAssessmentOperatorSpec. +func (in *ServersDatabasesVulnerabilityAssessmentOperatorSpec) DeepCopy() *ServersDatabasesVulnerabilityAssessmentOperatorSpec { + if in == nil { + return nil + } + out := new(ServersDatabasesVulnerabilityAssessmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesVulnerabilityAssessment_STATUS) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessment_STATUS) { *out = *in @@ -3216,6 +3780,11 @@ func (in *ServersDatabasesVulnerabilityAssessment_STATUS) DeepCopy() *ServersDat // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersDatabasesVulnerabilityAssessment_Spec) DeepCopyInto(out *ServersDatabasesVulnerabilityAssessment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersDatabasesVulnerabilityAssessmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3317,6 +3886,43 @@ func (in *ServersElasticPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersElasticPoolOperatorSpec) DeepCopyInto(out *ServersElasticPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersElasticPoolOperatorSpec. +func (in *ServersElasticPoolOperatorSpec) DeepCopy() *ServersElasticPoolOperatorSpec { + if in == nil { + return nil + } + out := new(ServersElasticPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersElasticPool_STATUS) DeepCopyInto(out *ServersElasticPool_STATUS) { *out = *in @@ -3454,6 +4060,11 @@ func (in *ServersElasticPool_Spec) DeepCopyInto(out *ServersElasticPool_Spec) { *out = new(float64) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersElasticPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3552,6 +4163,43 @@ func (in *ServersFailoverGroupList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersFailoverGroupOperatorSpec) DeepCopyInto(out *ServersFailoverGroupOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersFailoverGroupOperatorSpec. +func (in *ServersFailoverGroupOperatorSpec) DeepCopy() *ServersFailoverGroupOperatorSpec { + if in == nil { + return nil + } + out := new(ServersFailoverGroupOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersFailoverGroup_STATUS) DeepCopyInto(out *ServersFailoverGroup_STATUS) { *out = *in @@ -3641,6 +4289,11 @@ func (in *ServersFailoverGroup_Spec) DeepCopyInto(out *ServersFailoverGroup_Spec *out = make([]genruntime.ResourceReference, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersFailoverGroupOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3741,6 +4394,43 @@ func (in *ServersFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersFirewallRuleOperatorSpec) DeepCopyInto(out *ServersFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersFirewallRuleOperatorSpec. +func (in *ServersFirewallRuleOperatorSpec) DeepCopy() *ServersFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersFirewallRule_STATUS) DeepCopyInto(out *ServersFirewallRule_STATUS) { *out = *in @@ -3796,6 +4486,11 @@ func (in *ServersFirewallRule_Spec) DeepCopyInto(out *ServersFirewallRule_Spec) *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3877,6 +4572,43 @@ func (in *ServersIPV6FirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersIPV6FirewallRuleOperatorSpec) DeepCopyInto(out *ServersIPV6FirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersIPV6FirewallRuleOperatorSpec. +func (in *ServersIPV6FirewallRuleOperatorSpec) DeepCopy() *ServersIPV6FirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersIPV6FirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersIPV6FirewallRule_STATUS) DeepCopyInto(out *ServersIPV6FirewallRule_STATUS) { *out = *in @@ -3932,6 +4664,11 @@ func (in *ServersIPV6FirewallRule_Spec) DeepCopyInto(out *ServersIPV6FirewallRul *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersIPV6FirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4013,6 +4750,43 @@ func (in *ServersOutboundFirewallRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersOutboundFirewallRuleOperatorSpec) DeepCopyInto(out *ServersOutboundFirewallRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersOutboundFirewallRuleOperatorSpec. +func (in *ServersOutboundFirewallRuleOperatorSpec) DeepCopy() *ServersOutboundFirewallRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersOutboundFirewallRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersOutboundFirewallRule_STATUS) DeepCopyInto(out *ServersOutboundFirewallRule_STATUS) { *out = *in @@ -4058,6 +4832,11 @@ func (in *ServersOutboundFirewallRule_STATUS) DeepCopy() *ServersOutboundFirewal // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersOutboundFirewallRule_Spec) DeepCopyInto(out *ServersOutboundFirewallRule_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersOutboundFirewallRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4134,6 +4913,43 @@ func (in *ServersSecurityAlertPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersSecurityAlertPolicyOperatorSpec) DeepCopyInto(out *ServersSecurityAlertPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersSecurityAlertPolicyOperatorSpec. +func (in *ServersSecurityAlertPolicyOperatorSpec) DeepCopy() *ServersSecurityAlertPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(ServersSecurityAlertPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersSecurityAlertPolicy_STATUS) DeepCopyInto(out *ServersSecurityAlertPolicy_STATUS) { *out = *in @@ -4229,6 +5045,11 @@ func (in *ServersSecurityAlertPolicy_Spec) DeepCopyInto(out *ServersSecurityAler *out = make([]string, len(*in)) copy(*out, *in) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersSecurityAlertPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4325,6 +5146,43 @@ func (in *ServersVirtualNetworkRuleList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersVirtualNetworkRuleOperatorSpec) DeepCopyInto(out *ServersVirtualNetworkRuleOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersVirtualNetworkRuleOperatorSpec. +func (in *ServersVirtualNetworkRuleOperatorSpec) DeepCopy() *ServersVirtualNetworkRuleOperatorSpec { + if in == nil { + return nil + } + out := new(ServersVirtualNetworkRuleOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVirtualNetworkRule_STATUS) DeepCopyInto(out *ServersVirtualNetworkRule_STATUS) { *out = *in @@ -4385,6 +5243,11 @@ func (in *ServersVirtualNetworkRule_Spec) DeepCopyInto(out *ServersVirtualNetwor *out = new(bool) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersVirtualNetworkRuleOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4466,6 +5329,43 @@ func (in *ServersVulnerabilityAssessmentList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServersVulnerabilityAssessmentOperatorSpec) DeepCopyInto(out *ServersVulnerabilityAssessmentOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServersVulnerabilityAssessmentOperatorSpec. +func (in *ServersVulnerabilityAssessmentOperatorSpec) DeepCopy() *ServersVulnerabilityAssessmentOperatorSpec { + if in == nil { + return nil + } + out := new(ServersVulnerabilityAssessmentOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVulnerabilityAssessment_STATUS) DeepCopyInto(out *ServersVulnerabilityAssessment_STATUS) { *out = *in @@ -4516,6 +5416,11 @@ func (in *ServersVulnerabilityAssessment_STATUS) DeepCopy() *ServersVulnerabilit // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServersVulnerabilityAssessment_Spec) DeepCopyInto(out *ServersVulnerabilityAssessment_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServersVulnerabilityAssessmentOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20210401/storage/storage_account_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_account_types_gen.go index 84baba9037c..c7870433c95 100644 --- a/v2/api/storage/v1api20210401/storage/storage_account_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_account_types_gen.go @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -83,6 +85,26 @@ func (account *StorageAccount) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &StorageAccount{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -4390,9 +4412,11 @@ func (sku *Sku_STATUS) AssignProperties_To_Sku_STATUS(destination *storage.Sku_S // Storage version of v1api20210401.StorageAccountOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { - ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_StorageAccountOperatorSpec populates our StorageAccountOperatorSpec from the provided source StorageAccountOperatorSpec @@ -4400,6 +4424,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap StorageAccountOperatorConfigMaps @@ -4412,6 +4454,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret StorageAccountOperatorSecrets @@ -4449,6 +4509,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.StorageAccountOperatorConfigMaps @@ -4461,6 +4539,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.StorageAccountOperatorSecrets diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen.go index 1f9d8957962..b9629e5b22a 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20220901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (service *StorageAccountsBlobService) ConvertTo(hub conversion.Hub) error { return nil } +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobService{} // AzureName returns the Azure name of the resource (always "default") @@ -245,15 +268,16 @@ type augmentConversionForStorageAccountsBlobService interface { // Storage version of v1api20210401.StorageAccountsBlobService_Spec type StorageAccountsBlobService_Spec struct { - AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` - ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` - ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` - Cors *CorsRules `json:"cors,omitempty"` - DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` - DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` - IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` - LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` + ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` + ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` + DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` + IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` + LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -398,6 +422,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_From_StorageAcc service.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -525,6 +561,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_To_StorageAccou destination.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -1835,6 +1883,136 @@ func (properties *RestorePolicyProperties_STATUS) AssignProperties_To_RestorePol return nil } +// Storage version of v1api20210401.StorageAccountsBlobServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServiceOperatorSpec populates our StorageAccountsBlobServiceOperatorSpec from the provided source StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServiceOperatorSpec populates the provided destination StorageAccountsBlobServiceOperatorSpec from our StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(destination *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForChangeFeed interface { AssignPropertiesFrom(src *storage.ChangeFeed) error AssignPropertiesTo(dst *storage.ChangeFeed) error @@ -1885,6 +2063,11 @@ type augmentConversionForRestorePolicyProperties_STATUS interface { AssignPropertiesTo(dst *storage.RestorePolicyProperties_STATUS) error } +type augmentConversionForStorageAccountsBlobServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsBlobServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsBlobServiceOperatorSpec) error +} + // Storage version of v1api20210401.CorsRule // Specifies a CORS rule for the Blob service. type CorsRule struct { diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen_test.go index 40c4f9fa8fc..1aeca62c9f7 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_service_types_gen_test.go @@ -1418,6 +1418,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServiceOperatorSpec to StorageAccountsBlobServiceOperatorSpec via AssignProperties_To_StorageAccountsBlobServiceOperatorSpec & AssignProperties_From_StorageAccountsBlobServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec tests if a specific instance of StorageAccountsBlobServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsBlobServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1668,5 +1765,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen.go index 932b8916433..69fa7e6771d 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20220901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (container *StorageAccountsBlobServicesContainer) ConvertTo(hub conversion. return nil } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobServicesContainer{} // AzureName returns the Azure name of the resource @@ -248,12 +271,13 @@ type augmentConversionForStorageAccountsBlobServicesContainer interface { type StorageAccountsBlobServicesContainer_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` - DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` - ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` + DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` + ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -362,6 +386,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_Fro // Metadata container.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServicesContainerOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // OriginalVersion container.OriginalVersion = source.OriginalVersion @@ -456,6 +492,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_To_ // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(container.Metadata) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServicesContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = container.OriginalVersion @@ -1334,6 +1382,136 @@ func (properties *LegalHoldProperties_STATUS) AssignProperties_To_LegalHoldPrope return nil } +// Storage version of v1api20210401.StorageAccountsBlobServicesContainerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec populates our StorageAccountsBlobServicesContainerOperatorSpec from the provided source StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec populates the provided destination StorageAccountsBlobServicesContainerOperatorSpec from our StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(destination *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForImmutabilityPolicyProperties_STATUS interface { AssignPropertiesFrom(src *storage.ImmutabilityPolicyProperties_STATUS) error AssignPropertiesTo(dst *storage.ImmutabilityPolicyProperties_STATUS) error @@ -1354,6 +1532,11 @@ type augmentConversionForLegalHoldProperties_STATUS interface { AssignPropertiesTo(dst *storage.LegalHoldProperties_STATUS) error } +type augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsBlobServicesContainerOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsBlobServicesContainerOperatorSpec) error +} + // Storage version of v1api20210401.TagProperty_STATUS // A tag of the LegalHold of a blob container. type TagProperty_STATUS struct { diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen_test.go index 335c4ad9525..e00b5ee0f9b 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_blob_services_container_types_gen_test.go @@ -611,6 +611,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServicesContainerOperatorSpec to StorageAccountsBlobServicesContainerOperatorSpec via AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec & AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec tests if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsBlobServicesContainerOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -871,6 +968,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen.go index 2c12ade1a2b..fba98462048 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20220901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (policy *StorageAccountsManagementPolicy) ConvertTo(hub conversion.Hub) err return nil } +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsManagementPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -246,7 +269,8 @@ type augmentConversionForStorageAccountsManagementPolicy interface { // Storage version of v1api20210401.StorageAccountsManagementPolicy_Spec type StorageAccountsManagementPolicy_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -312,6 +336,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_From_Storag // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsManagementPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -360,6 +396,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_To_StorageA // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(policy.PropertyBag) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsManagementPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -766,6 +814,136 @@ func (schema *ManagementPolicySchema_STATUS) AssignProperties_To_ManagementPolic return nil } +// Storage version of v1api20210401.StorageAccountsManagementPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec populates our StorageAccountsManagementPolicyOperatorSpec from the provided source StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsManagementPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec populates the provided destination StorageAccountsManagementPolicyOperatorSpec from our StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(destination *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsManagementPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForManagementPolicySchema interface { AssignPropertiesFrom(src *storage.ManagementPolicySchema) error AssignPropertiesTo(dst *storage.ManagementPolicySchema) error @@ -776,6 +954,11 @@ type augmentConversionForManagementPolicySchema_STATUS interface { AssignPropertiesTo(dst *storage.ManagementPolicySchema_STATUS) error } +type augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsManagementPolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsManagementPolicyOperatorSpec) error +} + // Storage version of v1api20210401.ManagementPolicyRule // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen_test.go index 0365de761d0..f23fd678847 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_management_policy_types_gen_test.go @@ -2335,6 +2335,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsManagementPolicyOperatorSpec to StorageAccountsManagementPolicyOperatorSpec via AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec & AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec tests if a specific instance of StorageAccountsManagementPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsManagementPolicyOperatorSpec + err := copied.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsManagementPolicyOperatorSpec + err = actual.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2569,6 +2666,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gen // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen.go index b14d83369b1..42d01488c1b 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20220901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (service *StorageAccountsQueueService) ConvertTo(hub conversion.Hub) error return nil } +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueService{} // AzureName returns the Azure name of the resource (always "default") @@ -245,8 +268,9 @@ type augmentConversionForStorageAccountsQueueService interface { // Storage version of v1api20210401.StorageAccountsQueueService_Spec type StorageAccountsQueueService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -323,6 +347,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -371,6 +407,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -570,6 +618,141 @@ type augmentConversionForStorageAccountsQueueService_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsQueueService_STATUS) error } +// Storage version of v1api20210401.StorageAccountsQueueServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServiceOperatorSpec populates our StorageAccountsQueueServiceOperatorSpec from the provided source StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServiceOperatorSpec populates the provided destination StorageAccountsQueueServiceOperatorSpec from our StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(destination *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForStorageAccountsQueueServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsQueueServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsQueueServiceOperatorSpec) error +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen_test.go index c668bc08706..5a7203768a5 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_service_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServiceOperatorSpec to StorageAccountsQueueServiceOperatorSpec via AssignProperties_To_StorageAccountsQueueServiceOperatorSpec & AssignProperties_From_StorageAccountsQueueServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec tests if a specific instance of StorageAccountsQueueServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsQueueServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -400,4 +497,5 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueService_Spec(gens ma // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen.go index e770e985810..e72c4af6d3e 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen.go @@ -7,6 +7,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20220901/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -78,6 +81,26 @@ func (queue *StorageAccountsQueueServicesQueue) ConvertTo(hub conversion.Hub) er return nil } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueServicesQueue{} // AzureName returns the Azure name of the resource @@ -248,9 +271,10 @@ type augmentConversionForStorageAccountsQueueServicesQueue interface { type StorageAccountsQueueServicesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -321,6 +345,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_From_Stora // Metadata queue.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServicesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // OriginalVersion queue.OriginalVersion = source.OriginalVersion @@ -363,6 +399,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_To_Storage // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(queue.Metadata) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServicesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion @@ -551,6 +599,141 @@ type augmentConversionForStorageAccountsQueueServicesQueue_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsQueueServicesQueue_STATUS) error } +// Storage version of v1api20210401.StorageAccountsQueueServicesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec populates our StorageAccountsQueueServicesQueueOperatorSpec from the provided source StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec populates the provided destination StorageAccountsQueueServicesQueueOperatorSpec from our StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(destination *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsQueueServicesQueueOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsQueueServicesQueueOperatorSpec) error +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen_test.go index bd3559335ac..5a772246d71 100644 --- a/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage/storage_accounts_queue_services_queue_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServicesQueueOperatorSpec to StorageAccountsQueueServicesQueueOperatorSpec via AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec & AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec tests if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsQueueServicesQueueOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -370,6 +470,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -381,3 +487,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20210401/storage/structure.txt b/v2/api/storage/v1api20210401/storage/structure.txt index 7446262f1df..88e94eed4d2 100644 --- a/v2/api/storage/v1api20210401/storage/structure.txt +++ b/v2/api/storage/v1api20210401/storage/structure.txt @@ -93,7 +93,8 @@ StorageAccount: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── Reference: *genruntime.ResourceReference │ │ └── State: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (7 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -103,6 +104,7 @@ StorageAccount: Resource │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (9 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -325,7 +327,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: storage/v1api20210401.StorageAccount -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (3 properties) │ │ ├── Enabled: *bool @@ -356,6 +358,10 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -411,7 +417,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: storage/v1api20210401.StorageAccountsBlobService -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: string │ ├── DefaultEncryptionScope: *string │ ├── DenyEncryptionScopeOverride: *bool @@ -419,6 +425,10 @@ StorageAccountsBlobServicesContainer: Resource │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -475,7 +485,11 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: storage/v1api20210401.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Policy: *Object (2 properties) @@ -602,7 +616,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: storage/v1api20210401.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -612,6 +626,10 @@ StorageAccountsQueueService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -632,9 +650,13 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: storage/v1api20210401.StorageAccountsQueueService -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -732,18 +754,23 @@ augmentConversionForStorageAccountOperatorSpec: Interface augmentConversionForStorageAccount_STATUS: Interface augmentConversionForStorageAccount_Spec: Interface augmentConversionForStorageAccountsBlobService: Interface +augmentConversionForStorageAccountsBlobServiceOperatorSpec: Interface augmentConversionForStorageAccountsBlobService_STATUS: Interface augmentConversionForStorageAccountsBlobService_Spec: Interface augmentConversionForStorageAccountsBlobServicesContainer: Interface +augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec: Interface augmentConversionForStorageAccountsBlobServicesContainer_STATUS: Interface augmentConversionForStorageAccountsBlobServicesContainer_Spec: Interface augmentConversionForStorageAccountsManagementPolicy: Interface +augmentConversionForStorageAccountsManagementPolicyOperatorSpec: Interface augmentConversionForStorageAccountsManagementPolicy_STATUS: Interface augmentConversionForStorageAccountsManagementPolicy_Spec: Interface augmentConversionForStorageAccountsQueueService: Interface +augmentConversionForStorageAccountsQueueServiceOperatorSpec: Interface augmentConversionForStorageAccountsQueueService_STATUS: Interface augmentConversionForStorageAccountsQueueService_Spec: Interface augmentConversionForStorageAccountsQueueServicesQueue: Interface +augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec: Interface augmentConversionForStorageAccountsQueueServicesQueue_STATUS: Interface augmentConversionForStorageAccountsQueueServicesQueue_Spec: Interface augmentConversionForTagFilter: Interface diff --git a/v2/api/storage/v1api20210401/storage/zz_generated.deepcopy.go b/v2/api/storage/v1api20210401/storage/zz_generated.deepcopy.go index 072e07946f0..2d30499317c 100644 --- a/v2/api/storage/v1api20210401/storage/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20210401/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -3103,6 +3104,17 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) @@ -3115,6 +3127,17 @@ func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -3563,6 +3586,50 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -3700,6 +3767,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3788,6 +3860,50 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -3949,6 +4065,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4037,6 +4158,50 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -4094,6 +4259,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4182,6 +4352,50 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -4239,6 +4453,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4322,6 +4541,50 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -4388,6 +4651,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20210401/storage_account_types_gen.go b/v2/api/storage/v1api20210401/storage_account_types_gen.go index 2ae55b357f1..cd6359d44c5 100644 --- a/v2/api/storage/v1api20210401/storage_account_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_account_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (account *StorageAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccount resource func (account *StorageAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &StorageAccount{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -304,18 +325,18 @@ func (account *StorageAccount) validateConfigMapDestinations() (admission.Warnin if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, - account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, - account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, - account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, - account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, - account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + var toValidate []*genruntime.ConfigMapDestination + if account.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, + account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, + account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, + account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, + account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, + account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -337,20 +358,20 @@ func (account *StorageAccount) validateSecretDestinations() (admission.Warnings, if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - account.Spec.OperatorSpec.Secrets.BlobEndpoint, - account.Spec.OperatorSpec.Secrets.DfsEndpoint, - account.Spec.OperatorSpec.Secrets.FileEndpoint, - account.Spec.OperatorSpec.Secrets.Key1, - account.Spec.OperatorSpec.Secrets.Key2, - account.Spec.OperatorSpec.Secrets.QueueEndpoint, - account.Spec.OperatorSpec.Secrets.TableEndpoint, - account.Spec.OperatorSpec.Secrets.WebEndpoint, + var toValidate []*genruntime.SecretDestination + if account.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + account.Spec.OperatorSpec.Secrets.BlobEndpoint, + account.Spec.OperatorSpec.Secrets.DfsEndpoint, + account.Spec.OperatorSpec.Secrets.FileEndpoint, + account.Spec.OperatorSpec.Secrets.Key1, + account.Spec.OperatorSpec.Secrets.Key2, + account.Spec.OperatorSpec.Secrets.QueueEndpoint, + account.Spec.OperatorSpec.Secrets.TableEndpoint, + account.Spec.OperatorSpec.Secrets.WebEndpoint, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -6363,9 +6384,15 @@ var storageAccount_Kind_STATUS_Values = map[string]StorageAccount_Kind_STATUS{ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } @@ -6373,6 +6400,24 @@ type StorageAccountOperatorSpec struct { // AssignProperties_From_StorageAccountOperatorSpec populates our StorageAccountOperatorSpec from the provided source StorageAccountOperatorSpec func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccountOperatorSpec(source *storage.StorageAccountOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap StorageAccountOperatorConfigMaps @@ -6385,6 +6430,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret StorageAccountOperatorSecrets @@ -6406,6 +6469,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.StorageAccountOperatorConfigMaps @@ -6418,6 +6499,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.StorageAccountOperatorSecrets diff --git a/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen.go index 3b5f400e877..a9dea3423b6 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsBlobService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobService resource func (service *StorageAccountsBlobService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsBlobService) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (service *StorageAccountsBlobService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsBlobService) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsBlobService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsBlobService) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsBlobService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsBlobService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobService) @@ -348,6 +393,10 @@ type StorageAccountsBlobService_Spec struct { // LastAccessTimeTrackingPolicy: The blob service property to configure last access time based tracking policy. LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -554,6 +603,8 @@ func (service *StorageAccountsBlobService_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -710,6 +761,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_From_StorageAcc service.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -818,6 +881,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_To_StorageAccou destination.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -2501,6 +2576,110 @@ func (properties *RestorePolicyProperties_STATUS) AssignProperties_To_RestorePol return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServiceOperatorSpec populates our StorageAccountsBlobServiceOperatorSpec from the provided source StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source *storage.StorageAccountsBlobServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServiceOperatorSpec populates the provided destination StorageAccountsBlobServiceOperatorSpec from our StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(destination *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Specifies a CORS rule for the Blob service. type CorsRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen_test.go index 0045fd09cf6..a7648aa1db6 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage_accounts_blob_service_types_gen_test.go @@ -1432,6 +1432,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServiceOperatorSpec to StorageAccountsBlobServiceOperatorSpec via AssignProperties_To_StorageAccountsBlobServiceOperatorSpec & AssignProperties_From_StorageAccountsBlobServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec tests if a specific instance of StorageAccountsBlobServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401s.StorageAccountsBlobServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1681,5 +1778,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen.go index 6f80f5f6370..1facc2148e0 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (container *StorageAccountsBlobServicesContainer) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobServicesContainer resource func (container *StorageAccountsBlobServicesContainer) defaultImpl() { container.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobServicesContainer{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (container *StorageAccountsBlobServicesContainer) ValidateUpdate(old runtim // createValidations validates the creation of the resource func (container *StorageAccountsBlobServicesContainer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference} + return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference, container.validateSecretDestinations, container.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (container *StorageAccountsBlobServicesContainer) updateValidations() []fun func(old runtime.Object) (admission.Warnings, error) { return container.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (container *StorageAccountsBlobServicesContainer) validateConfigMapDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(container, nil, container.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (container *StorageAccountsBlobServicesContainer) validateResourceReference return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (container *StorageAccountsBlobServicesContainer) validateSecretDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(container, nil, container.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (container *StorageAccountsBlobServicesContainer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobServicesContainer) @@ -348,6 +393,10 @@ type StorageAccountsBlobServicesContainer_Spec struct { // Metadata: A name-value pair to associate with the container as metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -467,6 +516,8 @@ func (container *StorageAccountsBlobServicesContainer_Spec) PopulateFromARM(owne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": container.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -570,6 +621,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_Fro // Metadata container.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServicesContainerOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -625,6 +688,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_To_ // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(container.Metadata) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServicesContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = container.OriginalVersion() @@ -1886,6 +1961,110 @@ func (properties *LegalHoldProperties_STATUS) AssignProperties_To_LegalHoldPrope return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec populates our StorageAccountsBlobServicesContainerOperatorSpec from the provided source StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec populates the provided destination StorageAccountsBlobServicesContainerOperatorSpec from our StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(destination *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ImmutabilityPolicyProperty_State_STATUS string const ( diff --git a/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen_test.go index c9f116e52e2..a2a004f47e3 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage_accounts_blob_services_container_types_gen_test.go @@ -611,6 +611,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServicesContainerOperatorSpec to StorageAccountsBlobServicesContainerOperatorSpec via AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec & AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec tests if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401s.StorageAccountsBlobServicesContainerOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -875,6 +972,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen.go index 7ce1a9bd9f0..1a67fb16918 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (policy *StorageAccountsManagementPolicy) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsManagementPolicy resource func (policy *StorageAccountsManagementPolicy) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsManagementPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -205,7 +228,7 @@ func (policy *StorageAccountsManagementPolicy) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (policy *StorageAccountsManagementPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -223,7 +246,21 @@ func (policy *StorageAccountsManagementPolicy) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *StorageAccountsManagementPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -240,6 +277,14 @@ func (policy *StorageAccountsManagementPolicy) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *StorageAccountsManagementPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *StorageAccountsManagementPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsManagementPolicy) @@ -322,6 +367,10 @@ type StorageAccountsManagementPolicyList struct { } type StorageAccountsManagementPolicy_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -373,6 +422,8 @@ func (policy *StorageAccountsManagementPolicy_Spec) PopulateFromARM(owner genrun return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.StorageAccountsManagementPolicy_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -450,6 +501,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) ConvertSpecTo(destination ge // AssignProperties_From_StorageAccountsManagementPolicy_Spec populates our StorageAccountsManagementPolicy_Spec from the provided source StorageAccountsManagementPolicy_Spec func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_From_StorageAccountsManagementPolicy_Spec(source *storage.StorageAccountsManagementPolicy_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsManagementPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -479,6 +542,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_To_StorageA // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsManagementPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -937,6 +1012,110 @@ func (schema *ManagementPolicySchema_STATUS) AssignProperties_To_ManagementPolic return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec populates our StorageAccountsManagementPolicyOperatorSpec from the provided source StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source *storage.StorageAccountsManagementPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec populates the provided destination StorageAccountsManagementPolicyOperatorSpec from our StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(destination *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen_test.go index a55236e914b..daa297f8da5 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage_accounts_management_policy_types_gen_test.go @@ -2335,6 +2335,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsManagementPolicyOperatorSpec to StorageAccountsManagementPolicyOperatorSpec via AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec & AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec tests if a specific instance of StorageAccountsManagementPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401s.StorageAccountsManagementPolicyOperatorSpec + err := copied.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsManagementPolicyOperatorSpec + err = actual.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2555,6 +2652,7 @@ func StorageAccountsManagementPolicy_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen.go index d35949ec413..5aa845c6e00 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsQueueService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueService resource func (service *StorageAccountsQueueService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsQueueService) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (service *StorageAccountsQueueService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsQueueService) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsQueueService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsQueueService) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsQueueService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsQueueService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueService) @@ -326,6 +371,10 @@ type StorageAccountsQueueService_Spec struct { // Queue service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (service *StorageAccountsQueueService_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -461,6 +512,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -490,6 +553,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -710,6 +785,110 @@ func (service *StorageAccountsQueueService_STATUS) AssignProperties_To_StorageAc return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServiceOperatorSpec populates our StorageAccountsQueueServiceOperatorSpec from the provided source StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source *storage.StorageAccountsQueueServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServiceOperatorSpec populates the provided destination StorageAccountsQueueServiceOperatorSpec from our StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(destination *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen_test.go index 20654de4dcd..59e8881daaf 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage_accounts_queue_service_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServiceOperatorSpec to StorageAccountsQueueServiceOperatorSpec via AssignProperties_To_StorageAccountsQueueServiceOperatorSpec & AssignProperties_From_StorageAccountsQueueServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec tests if a specific instance of StorageAccountsQueueServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401s.StorageAccountsQueueServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,4 +483,5 @@ func StorageAccountsQueueService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen.go index 01728bc1dbd..d19ef5cde62 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (queue *StorageAccountsQueueServicesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueServicesQueue resource func (queue *StorageAccountsQueueServicesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueServicesQueue{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (queue *StorageAccountsQueueServicesQueue) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (queue *StorageAccountsQueueServicesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (queue *StorageAccountsQueueServicesQueue) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *StorageAccountsQueueServicesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (queue *StorageAccountsQueueServicesQueue) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *StorageAccountsQueueServicesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *StorageAccountsQueueServicesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueServicesQueue) @@ -338,6 +383,10 @@ type StorageAccountsQueueServicesQueue_Spec struct { // Metadata: A name-value pair that represents queue metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -396,6 +445,8 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) PopulateFromARM(owner genru } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -465,6 +516,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_From_Stora // Metadata queue.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServicesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -488,6 +551,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_To_Storage // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(queue.Metadata) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServicesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -709,6 +784,110 @@ func (queue *StorageAccountsQueueServicesQueue_STATUS) AssignProperties_To_Stora return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec populates our StorageAccountsQueueServicesQueueOperatorSpec from the provided source StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec populates the provided destination StorageAccountsQueueServicesQueueOperatorSpec from our StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(destination *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen_test.go index 3946f6fc65e..570b4d28afa 100644 --- a/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20210401/storage_accounts_queue_services_queue_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServicesQueueOperatorSpec to StorageAccountsQueueServicesQueueOperatorSpec via AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec & AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec tests if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20210401s.StorageAccountsQueueServicesQueueOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -370,6 +470,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -380,3 +486,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20210401/structure.txt b/v2/api/storage/v1api20210401/structure.txt index 9ca67183901..6eb3438f357 100644 --- a/v2/api/storage/v1api20210401/structure.txt +++ b/v2/api/storage/v1api20210401/structure.txt @@ -120,7 +120,8 @@ StorageAccount: Resource │ │ ├── "NetworkSourceDeleted" │ │ ├── "Provisioning" │ │ └── "Succeeded" -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (6 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -128,6 +129,7 @@ StorageAccount: Resource │ │ │ ├── QueueEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (8 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -396,7 +398,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: StorageAccount -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (2 properties) │ │ ├── Enabled: *bool @@ -435,6 +437,9 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *Enum (1 value) │ │ │ └── "AccessTimeTracking" │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RestorePolicy: *Object (2 properties) │ ├── Days: Validated<*int> (2 rules) @@ -498,7 +503,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: StorageAccountsBlobService -├── Spec: Object (7 properties) +├── Spec: Object (8 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 @@ -507,6 +512,9 @@ StorageAccountsBlobServicesContainer: Resource │ ├── ImmutableStorageWithVersioning: *Object (1 property) │ │ └── Enabled: *bool │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── PublicAccess: *Enum (3 values) │ ├── "Blob" @@ -577,7 +585,10 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Policy: *Object (1 property) │ └── Rules: Object (4 properties)[] @@ -695,7 +706,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -710,6 +721,9 @@ StorageAccountsQueueService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -732,11 +746,14 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: StorageAccountsQueueService -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (6 properties) ├── ApproximateMessageCount: *int diff --git a/v2/api/storage/v1api20210401/zz_generated.deepcopy.go b/v2/api/storage/v1api20210401/zz_generated.deepcopy.go index 8b6a1b506b5..6c1c63472bc 100644 --- a/v2/api/storage/v1api20210401/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20210401/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210401 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -2534,11 +2535,33 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -2973,6 +2996,43 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -3103,6 +3163,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3184,6 +3249,43 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -3338,6 +3440,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3419,6 +3526,43 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -3469,6 +3613,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3550,6 +3699,43 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -3600,6 +3786,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3676,6 +3867,43 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -3735,6 +3963,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20220901/storage/storage_account_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_account_types_gen.go index 521af2df8d8..337881dd0d5 100644 --- a/v2/api/storage/v1api20220901/storage/storage_account_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_account_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -70,6 +72,26 @@ func (account *StorageAccount) ConvertTo(hub conversion.Hub) error { return account.AssignProperties_To_StorageAccount(destination) } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &StorageAccount{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -4592,9 +4614,11 @@ func (sku *Sku_STATUS) AssignProperties_To_Sku_STATUS(destination *storage.Sku_S // Storage version of v1api20220901.StorageAccountOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { - ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } // AssignProperties_From_StorageAccountOperatorSpec populates our StorageAccountOperatorSpec from the provided source StorageAccountOperatorSpec @@ -4602,6 +4626,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap StorageAccountOperatorConfigMaps @@ -4614,6 +4656,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret StorageAccountOperatorSecrets @@ -4651,6 +4711,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.StorageAccountOperatorConfigMaps @@ -4663,6 +4741,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.StorageAccountOperatorSecrets diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen.go index ecf4bd869bb..a5715c6ea95 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (service *StorageAccountsBlobService) ConvertTo(hub conversion.Hub) error { return service.AssignProperties_To_StorageAccountsBlobService(destination) } +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobService{} // AzureName returns the Azure name of the resource (always "default") @@ -232,15 +255,16 @@ type augmentConversionForStorageAccountsBlobService interface { // Storage version of v1api20220901.StorageAccountsBlobService_Spec type StorageAccountsBlobService_Spec struct { - AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` - ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` - ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` - Cors *CorsRules `json:"cors,omitempty"` - DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` - DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` - IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` - LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` + ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` + ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` + DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` + IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` + LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -385,6 +409,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_From_StorageAcc service.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -512,6 +548,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_To_StorageAccou destination.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -1816,6 +1864,136 @@ func (properties *RestorePolicyProperties_STATUS) AssignProperties_To_RestorePol return nil } +// Storage version of v1api20220901.StorageAccountsBlobServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServiceOperatorSpec populates our StorageAccountsBlobServiceOperatorSpec from the provided source StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServiceOperatorSpec populates the provided destination StorageAccountsBlobServiceOperatorSpec from our StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(destination *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForChangeFeed interface { AssignPropertiesFrom(src *storage.ChangeFeed) error AssignPropertiesTo(dst *storage.ChangeFeed) error @@ -1866,6 +2044,11 @@ type augmentConversionForRestorePolicyProperties_STATUS interface { AssignPropertiesTo(dst *storage.RestorePolicyProperties_STATUS) error } +type augmentConversionForStorageAccountsBlobServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsBlobServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsBlobServiceOperatorSpec) error +} + // Storage version of v1api20220901.CorsRule // Specifies a CORS rule for the Blob service. type CorsRule struct { diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen_test.go index 090b1473054..c7f76b7fa4f 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_service_types_gen_test.go @@ -1419,6 +1419,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServiceOperatorSpec to StorageAccountsBlobServiceOperatorSpec via AssignProperties_To_StorageAccountsBlobServiceOperatorSpec & AssignProperties_From_StorageAccountsBlobServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec tests if a specific instance of StorageAccountsBlobServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsBlobServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1669,5 +1766,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen.go index 9518e33b1d8..b47d457aa6b 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (container *StorageAccountsBlobServicesContainer) ConvertTo(hub conversion. return container.AssignProperties_To_StorageAccountsBlobServicesContainer(destination) } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobServicesContainer{} // AzureName returns the Azure name of the resource @@ -235,14 +258,15 @@ type augmentConversionForStorageAccountsBlobServicesContainer interface { type StorageAccountsBlobServicesContainer_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` - DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` - EnableNfsV3AllSquash *bool `json:"enableNfsV3AllSquash,omitempty"` - EnableNfsV3RootSquash *bool `json:"enableNfsV3RootSquash,omitempty"` - ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` + DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` + EnableNfsV3AllSquash *bool `json:"enableNfsV3AllSquash,omitempty"` + EnableNfsV3RootSquash *bool `json:"enableNfsV3RootSquash,omitempty"` + ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -353,6 +377,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_Fro // Metadata container.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServicesContainerOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // OriginalVersion container.OriginalVersion = source.OriginalVersion @@ -437,6 +473,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_To_ // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(container.Metadata) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServicesContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = container.OriginalVersion @@ -1311,6 +1359,136 @@ func (properties *LegalHoldProperties_STATUS) AssignProperties_To_LegalHoldPrope return nil } +// Storage version of v1api20220901.StorageAccountsBlobServicesContainerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec populates our StorageAccountsBlobServicesContainerOperatorSpec from the provided source StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec populates the provided destination StorageAccountsBlobServicesContainerOperatorSpec from our StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(destination *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForImmutabilityPolicyProperties_STATUS interface { AssignPropertiesFrom(src *storage.ImmutabilityPolicyProperties_STATUS) error AssignPropertiesTo(dst *storage.ImmutabilityPolicyProperties_STATUS) error @@ -1331,6 +1509,11 @@ type augmentConversionForLegalHoldProperties_STATUS interface { AssignPropertiesTo(dst *storage.LegalHoldProperties_STATUS) error } +type augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsBlobServicesContainerOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsBlobServicesContainerOperatorSpec) error +} + // Storage version of v1api20220901.ProtectedAppendWritesHistory_STATUS // Protected append writes history setting for the blob container with Legal holds. type ProtectedAppendWritesHistory_STATUS struct { diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen_test.go index 7c430d02602..e5dc7cb50f4 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_blob_services_container_types_gen_test.go @@ -716,6 +716,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServicesContainerOperatorSpec to StorageAccountsBlobServicesContainerOperatorSpec via AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec & AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec tests if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsBlobServicesContainerOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -980,6 +1077,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen.go index 09c44777c75..fc5c2286bf0 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (service *StorageAccountsFileService) ConvertTo(hub conversion.Hub) error { return service.AssignProperties_To_StorageAccountsFileService(destination) } +var _ configmaps.Exporter = &StorageAccountsFileService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsFileService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsFileService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileService{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForStorageAccountsFileService interface { // Storage version of v1api20220901.StorageAccountsFileService_Spec type StorageAccountsFileService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsFileServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -312,6 +336,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_From_StorageAcc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -384,6 +420,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_To_StorageAccou destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -844,6 +892,136 @@ func (settings *ProtocolSettings_STATUS) AssignProperties_To_ProtocolSettings_ST return nil } +// Storage version of v1api20220901.StorageAccountsFileServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServiceOperatorSpec populates our StorageAccountsFileServiceOperatorSpec from the provided source StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source *storage.StorageAccountsFileServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsFileServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsFileServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServiceOperatorSpec populates the provided destination StorageAccountsFileServiceOperatorSpec from our StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_To_StorageAccountsFileServiceOperatorSpec(destination *storage.StorageAccountsFileServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsFileServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsFileServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForProtocolSettings interface { AssignPropertiesFrom(src *storage.ProtocolSettings) error AssignPropertiesTo(dst *storage.ProtocolSettings) error @@ -854,6 +1032,11 @@ type augmentConversionForProtocolSettings_STATUS interface { AssignPropertiesTo(dst *storage.ProtocolSettings_STATUS) error } +type augmentConversionForStorageAccountsFileServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsFileServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsFileServiceOperatorSpec) error +} + // Storage version of v1api20220901.SmbSetting // Setting for SMB protocol type SmbSetting struct { diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen_test.go index 2e3bedb2b5c..eb1e28d6b10 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_file_service_types_gen_test.go @@ -813,6 +813,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileService(gens map[string]g gens["Status"] = StorageAccountsFileService_STATUSGenerator() } +func Test_StorageAccountsFileServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServiceOperatorSpec to StorageAccountsFileServiceOperatorSpec via AssignProperties_To_StorageAccountsFileServiceOperatorSpec & AssignProperties_From_StorageAccountsFileServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec tests if a specific instance of StorageAccountsFileServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsFileServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServiceOperatorSpecGenerator() +var storageAccountsFileServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServiceOperatorSpecGenerator returns a generator of StorageAccountsFileServiceOperatorSpec instances for property testing. +func StorageAccountsFileServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServiceOperatorSpecGenerator != nil { + return storageAccountsFileServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServiceOperatorSpec{}), generators) + + return storageAccountsFileServiceOperatorSpecGenerator +} + func Test_StorageAccountsFileService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1050,6 +1147,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileService_Spec(gens map // AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServiceOperatorSpecGenerator()) gens["ProtocolSettings"] = gen.PtrOf(ProtocolSettingsGenerator()) gens["ShareDeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen.go index 08dc9eb6b3d..65d407b4b3f 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (share *StorageAccountsFileServicesShare) ConvertTo(hub conversion.Hub) err return share.AssignProperties_To_StorageAccountsFileServicesShare(destination) } +var _ configmaps.Exporter = &StorageAccountsFileServicesShare{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (share *StorageAccountsFileServicesShare) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileServicesShare{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (share *StorageAccountsFileServicesShare) SecretDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileServicesShare{} // AzureName returns the Azure name of the resource @@ -237,10 +260,11 @@ type StorageAccountsFileServicesShare_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnabledProtocols *string `json:"enabledProtocols,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnabledProtocols *string `json:"enabledProtocols,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsFileServicesShareOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -320,6 +344,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_From_Storag // Metadata share.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServicesShareOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + share.OperatorSpec = &operatorSpec + } else { + share.OperatorSpec = nil + } + // OriginalVersion share.OriginalVersion = source.OriginalVersion @@ -392,6 +428,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_To_StorageA // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(share.Metadata) + // OperatorSpec + if share.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServicesShareOperatorSpec + err := share.OperatorSpec.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = share.OriginalVersion @@ -949,6 +997,136 @@ func (identifier *SignedIdentifier_STATUS) AssignProperties_To_SignedIdentifier_ return nil } +// Storage version of v1api20220901.StorageAccountsFileServicesShareOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServicesShareOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec populates our StorageAccountsFileServicesShareOperatorSpec from the provided source StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source *storage.StorageAccountsFileServicesShareOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsFileServicesShareOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsFileServicesShareOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec populates the provided destination StorageAccountsFileServicesShareOperatorSpec from our StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(destination *storage.StorageAccountsFileServicesShareOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsFileServicesShareOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsFileServicesShareOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20220901.AccessPolicy type AccessPolicy struct { ExpiryTime *string `json:"expiryTime,omitempty"` @@ -1111,6 +1289,11 @@ type augmentConversionForSignedIdentifier_STATUS interface { AssignPropertiesTo(dst *storage.SignedIdentifier_STATUS) error } +type augmentConversionForStorageAccountsFileServicesShareOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsFileServicesShareOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsFileServicesShareOperatorSpec) error +} + type augmentConversionForAccessPolicy interface { AssignPropertiesFrom(src *storage.AccessPolicy) error AssignPropertiesTo(dst *storage.AccessPolicy) error diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen_test.go index 59307c23f73..be13639f5d1 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_file_services_share_types_gen_test.go @@ -593,6 +593,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare(gens map[st gens["Status"] = StorageAccountsFileServicesShare_STATUSGenerator() } +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServicesShareOperatorSpec to StorageAccountsFileServicesShareOperatorSpec via AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec & AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec tests if a specific instance of StorageAccountsFileServicesShareOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsFileServicesShareOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServicesShareOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServicesShareOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServicesShareOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServicesShareOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServicesShareOperatorSpecGenerator() +var storageAccountsFileServicesShareOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServicesShareOperatorSpecGenerator returns a generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing. +func StorageAccountsFileServicesShareOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServicesShareOperatorSpecGenerator != nil { + return storageAccountsFileServicesShareOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServicesShareOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServicesShareOperatorSpec{}), generators) + + return storageAccountsFileServicesShareOperatorSpecGenerator +} + func Test_StorageAccountsFileServicesShare_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -854,5 +951,6 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(ge // AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServicesShareOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(SignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen.go index a11fd067875..0e168d0ea53 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (policy *StorageAccountsManagementPolicy) ConvertTo(hub conversion.Hub) err return policy.AssignProperties_To_StorageAccountsManagementPolicy(destination) } +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsManagementPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -233,7 +256,8 @@ type augmentConversionForStorageAccountsManagementPolicy interface { // Storage version of v1api20220901.StorageAccountsManagementPolicy_Spec type StorageAccountsManagementPolicy_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -299,6 +323,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_From_Storag // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsManagementPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // OriginalVersion policy.OriginalVersion = source.OriginalVersion @@ -347,6 +383,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_To_StorageA // Clone the existing property bag propertyBag := genruntime.NewPropertyBag(policy.PropertyBag) + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsManagementPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion @@ -753,6 +801,136 @@ func (schema *ManagementPolicySchema_STATUS) AssignProperties_To_ManagementPolic return nil } +// Storage version of v1api20220901.StorageAccountsManagementPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec populates our StorageAccountsManagementPolicyOperatorSpec from the provided source StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsManagementPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec populates the provided destination StorageAccountsManagementPolicyOperatorSpec from our StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(destination *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsManagementPolicyOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + type augmentConversionForManagementPolicySchema interface { AssignPropertiesFrom(src *storage.ManagementPolicySchema) error AssignPropertiesTo(dst *storage.ManagementPolicySchema) error @@ -763,6 +941,11 @@ type augmentConversionForManagementPolicySchema_STATUS interface { AssignPropertiesTo(dst *storage.ManagementPolicySchema_STATUS) error } +type augmentConversionForStorageAccountsManagementPolicyOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsManagementPolicyOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsManagementPolicyOperatorSpec) error +} + // Storage version of v1api20220901.ManagementPolicyRule // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen_test.go index ba42aff0f76..81cacbd6f4c 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_management_policy_types_gen_test.go @@ -2352,6 +2352,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsManagementPolicyOperatorSpec to StorageAccountsManagementPolicyOperatorSpec via AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec & AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec tests if a specific instance of StorageAccountsManagementPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsManagementPolicyOperatorSpec + err := copied.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsManagementPolicyOperatorSpec + err = actual.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2586,6 +2683,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gen // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen.go index 419922fa7a4..cb06fbbd515 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (service *StorageAccountsQueueService) ConvertTo(hub conversion.Hub) error return service.AssignProperties_To_StorageAccountsQueueService(destination) } +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueService{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForStorageAccountsQueueService interface { // Storage version of v1api20220901.StorageAccountsQueueService_Spec type StorageAccountsQueueService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -310,6 +334,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -358,6 +394,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -557,6 +605,141 @@ type augmentConversionForStorageAccountsQueueService_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsQueueService_STATUS) error } +// Storage version of v1api20220901.StorageAccountsQueueServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServiceOperatorSpec populates our StorageAccountsQueueServiceOperatorSpec from the provided source StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServiceOperatorSpec populates the provided destination StorageAccountsQueueServiceOperatorSpec from our StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(destination *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForStorageAccountsQueueServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsQueueServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsQueueServiceOperatorSpec) error +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen_test.go index 75c2a42bd53..3c8373c7d0d 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_service_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServiceOperatorSpec to StorageAccountsQueueServiceOperatorSpec via AssignProperties_To_StorageAccountsQueueServiceOperatorSpec & AssignProperties_From_StorageAccountsQueueServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec tests if a specific instance of StorageAccountsQueueServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsQueueServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,4 +496,5 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueService_Spec(gens ma // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen.go index 9b19e5cd0bb..d4ac7a4c46c 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (queue *StorageAccountsQueueServicesQueue) ConvertTo(hub conversion.Hub) er return queue.AssignProperties_To_StorageAccountsQueueServicesQueue(destination) } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueServicesQueue{} // AzureName returns the Azure name of the resource @@ -235,9 +258,10 @@ type augmentConversionForStorageAccountsQueueServicesQueue interface { type StorageAccountsQueueServicesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -308,6 +332,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_From_Stora // Metadata queue.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServicesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // OriginalVersion queue.OriginalVersion = source.OriginalVersion @@ -350,6 +386,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_To_Storage // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(queue.Metadata) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServicesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion @@ -538,6 +586,141 @@ type augmentConversionForStorageAccountsQueueServicesQueue_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsQueueServicesQueue_STATUS) error } +// Storage version of v1api20220901.StorageAccountsQueueServicesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec populates our StorageAccountsQueueServicesQueueOperatorSpec from the provided source StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec populates the provided destination StorageAccountsQueueServicesQueueOperatorSpec from our StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(destination *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsQueueServicesQueueOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsQueueServicesQueueOperatorSpec) error +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen_test.go index d11b018d7f4..51aefc753ff 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_queue_services_queue_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServicesQueueOperatorSpec to StorageAccountsQueueServicesQueueOperatorSpec via AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec & AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec tests if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsQueueServicesQueueOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -369,6 +469,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -380,3 +486,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen.go index 7877eed4186..cfda4995f4e 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (service *StorageAccountsTableService) ConvertTo(hub conversion.Hub) error return service.AssignProperties_To_StorageAccountsTableService(destination) } +var _ configmaps.Exporter = &StorageAccountsTableService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsTableService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsTableService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableService{} // AzureName returns the Azure name of the resource (always "default") @@ -232,8 +255,9 @@ type augmentConversionForStorageAccountsTableService interface { // Storage version of v1api20220901.StorageAccountsTableService_Spec type StorageAccountsTableService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsTableServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -310,6 +334,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // OriginalVersion service.OriginalVersion = source.OriginalVersion @@ -358,6 +394,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion @@ -557,6 +605,141 @@ type augmentConversionForStorageAccountsTableService_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsTableService_STATUS) error } +// Storage version of v1api20220901.StorageAccountsTableServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServiceOperatorSpec populates our StorageAccountsTableServiceOperatorSpec from the provided source StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source *storage.StorageAccountsTableServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsTableServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsTableServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServiceOperatorSpec populates the provided destination StorageAccountsTableServiceOperatorSpec from our StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_To_StorageAccountsTableServiceOperatorSpec(destination *storage.StorageAccountsTableServiceOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsTableServiceOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsTableServiceOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + +type augmentConversionForStorageAccountsTableServiceOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsTableServiceOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsTableServiceOperatorSpec) error +} + func init() { SchemeBuilder.Register(&StorageAccountsTableService{}, &StorageAccountsTableServiceList{}) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen_test.go index e7caec43b78..c2b42f4d000 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_table_service_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableService(gens map[string] gens["Status"] = StorageAccountsTableService_STATUSGenerator() } +func Test_StorageAccountsTableServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServiceOperatorSpec to StorageAccountsTableServiceOperatorSpec via AssignProperties_To_StorageAccountsTableServiceOperatorSpec & AssignProperties_From_StorageAccountsTableServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec tests if a specific instance of StorageAccountsTableServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsTableServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServiceOperatorSpecGenerator() +var storageAccountsTableServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServiceOperatorSpecGenerator returns a generator of StorageAccountsTableServiceOperatorSpec instances for property testing. +func StorageAccountsTableServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServiceOperatorSpecGenerator != nil { + return storageAccountsTableServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServiceOperatorSpec{}), generators) + + return storageAccountsTableServiceOperatorSpecGenerator +} + func Test_StorageAccountsTableService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,4 +496,5 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableService_Spec(gens ma // AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen.go b/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen.go index f58d386137f..75ca9caefd5 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen.go @@ -8,6 +8,9 @@ import ( storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101/storage" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -65,6 +68,26 @@ func (table *StorageAccountsTableServicesTable) ConvertTo(hub conversion.Hub) er return table.AssignProperties_To_StorageAccountsTableServicesTable(destination) } +var _ configmaps.Exporter = &StorageAccountsTableServicesTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *StorageAccountsTableServicesTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableServicesTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *StorageAccountsTableServicesTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableServicesTable{} // AzureName returns the Azure name of the resource @@ -235,8 +258,9 @@ type augmentConversionForStorageAccountsTableServicesTable interface { type StorageAccountsTableServicesTable_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *StorageAccountsTableServicesTableOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -305,6 +329,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_From_Stora // AzureName table.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServicesTableOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + table.OperatorSpec = &operatorSpec + } else { + table.OperatorSpec = nil + } + // OriginalVersion table.OriginalVersion = source.OriginalVersion @@ -362,6 +398,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_To_Storage // AzureName destination.AzureName = table.AzureName + // OperatorSpec + if table.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServicesTableOperatorSpec + err := table.OperatorSpec.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = table.OriginalVersion @@ -598,6 +646,136 @@ type augmentConversionForStorageAccountsTableServicesTable_STATUS interface { AssignPropertiesTo(dst *storage.StorageAccountsTableServicesTable_STATUS) error } +// Storage version of v1api20220901.StorageAccountsTableServicesTableOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServicesTableOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec populates our StorageAccountsTableServicesTableOperatorSpec from the provided source StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source *storage.StorageAccountsTableServicesTableOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(source.PropertyBag) + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + operator.PropertyBag = propertyBag + } else { + operator.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsTableServicesTableOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsTableServicesTableOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesFrom(source) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesFrom() for conversion") + } + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec populates the provided destination StorageAccountsTableServicesTableOperatorSpec from our StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(destination *storage.StorageAccountsTableServicesTableOperatorSpec) error { + // Clone the existing property bag + propertyBag := genruntime.NewPropertyBag(operator.PropertyBag) + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // Invoke the augmentConversionForStorageAccountsTableServicesTableOperatorSpec interface (if implemented) to customize the conversion + var operatorAsAny any = operator + if augmentedOperator, ok := operatorAsAny.(augmentConversionForStorageAccountsTableServicesTableOperatorSpec); ok { + err := augmentedOperator.AssignPropertiesTo(destination) + if err != nil { + return errors.Wrap(err, "calling augmented AssignPropertiesTo() for conversion") + } + } + + // No error + return nil +} + // Storage version of v1api20220901.TableSignedIdentifier // Object to set Table Access Policy. type TableSignedIdentifier struct { @@ -787,6 +965,11 @@ func (identifier *TableSignedIdentifier_STATUS) AssignProperties_To_TableSignedI return nil } +type augmentConversionForStorageAccountsTableServicesTableOperatorSpec interface { + AssignPropertiesFrom(src *storage.StorageAccountsTableServicesTableOperatorSpec) error + AssignPropertiesTo(dst *storage.StorageAccountsTableServicesTableOperatorSpec) error +} + type augmentConversionForTableSignedIdentifier interface { AssignPropertiesFrom(src *storage.TableSignedIdentifier) error AssignPropertiesTo(dst *storage.TableSignedIdentifier) error diff --git a/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen_test.go b/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen_test.go index 15f50ca4c04..1189e619602 100644 --- a/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage/storage_accounts_table_services_table_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable(gens map[s gens["Status"] = StorageAccountsTableServicesTable_STATUSGenerator() } +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServicesTableOperatorSpec to StorageAccountsTableServicesTableOperatorSpec via AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec & AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec tests if a specific instance of StorageAccountsTableServicesTableOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsTableServicesTableOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServicesTableOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServicesTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServicesTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServicesTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServicesTableOperatorSpecGenerator() +var storageAccountsTableServicesTableOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServicesTableOperatorSpecGenerator returns a generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing. +func StorageAccountsTableServicesTableOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServicesTableOperatorSpecGenerator != nil { + return storageAccountsTableServicesTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServicesTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServicesTableOperatorSpec{}), generators) + + return storageAccountsTableServicesTableOperatorSpecGenerator +} + func Test_StorageAccountsTableServicesTable_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -400,6 +497,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(g // AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServicesTableOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(TableSignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage/structure.txt b/v2/api/storage/v1api20220901/storage/structure.txt index 96b220a2178..c8ae53c6e7c 100644 --- a/v2/api/storage/v1api20220901/storage/structure.txt +++ b/v2/api/storage/v1api20220901/storage/structure.txt @@ -109,7 +109,8 @@ StorageAccount: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── Reference: *genruntime.ResourceReference │ │ └── State: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (7 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -119,6 +120,7 @@ StorageAccount: Resource │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (9 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -366,7 +368,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: storage/v1api20220901.StorageAccount -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (3 properties) │ │ ├── Enabled: *bool @@ -399,6 +401,10 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -456,7 +462,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: storage/v1api20220901.StorageAccountsBlobService -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── DefaultEncryptionScope: *string │ ├── DenyEncryptionScopeOverride: *bool @@ -466,6 +472,10 @@ StorageAccountsBlobServicesContainer: Resource │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -531,7 +541,7 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsFileService: Resource ├── Owner: storage/v1api20220901.StorageAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -541,6 +551,10 @@ StorageAccountsFileService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -597,11 +611,15 @@ StorageAccountsFileService: Resource └── Type: *string StorageAccountsFileServicesShare: Resource ├── Owner: storage/v1api20220901.StorageAccountsFileService -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AccessTier: *string │ ├── AzureName: string │ ├── EnabledProtocols: *string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -649,7 +667,11 @@ StorageAccountsFileServicesShare: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: storage/v1api20220901.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Policy: *Object (2 properties) @@ -856,7 +878,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: storage/v1api20220901.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -866,6 +888,10 @@ StorageAccountsQueueService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -886,9 +912,13 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: storage/v1api20220901.StorageAccountsQueueService -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -902,7 +932,7 @@ StorageAccountsQueueServicesQueue: Resource └── Type: *string StorageAccountsTableService: Resource ├── Owner: storage/v1api20220901.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -912,6 +942,10 @@ StorageAccountsTableService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -932,8 +966,12 @@ StorageAccountsTableService: Resource └── Type: *string StorageAccountsTableServicesTable: Resource ├── Owner: storage/v1api20220901.StorageAccountsTableService -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -1062,30 +1100,39 @@ augmentConversionForStorageAccountSkuConversionStatus_STATUS: Interface augmentConversionForStorageAccount_STATUS: Interface augmentConversionForStorageAccount_Spec: Interface augmentConversionForStorageAccountsBlobService: Interface +augmentConversionForStorageAccountsBlobServiceOperatorSpec: Interface augmentConversionForStorageAccountsBlobService_STATUS: Interface augmentConversionForStorageAccountsBlobService_Spec: Interface augmentConversionForStorageAccountsBlobServicesContainer: Interface +augmentConversionForStorageAccountsBlobServicesContainerOperatorSpec: Interface augmentConversionForStorageAccountsBlobServicesContainer_STATUS: Interface augmentConversionForStorageAccountsBlobServicesContainer_Spec: Interface augmentConversionForStorageAccountsFileService: Interface +augmentConversionForStorageAccountsFileServiceOperatorSpec: Interface augmentConversionForStorageAccountsFileService_STATUS: Interface augmentConversionForStorageAccountsFileService_Spec: Interface augmentConversionForStorageAccountsFileServicesShare: Interface +augmentConversionForStorageAccountsFileServicesShareOperatorSpec: Interface augmentConversionForStorageAccountsFileServicesShare_STATUS: Interface augmentConversionForStorageAccountsFileServicesShare_Spec: Interface augmentConversionForStorageAccountsManagementPolicy: Interface +augmentConversionForStorageAccountsManagementPolicyOperatorSpec: Interface augmentConversionForStorageAccountsManagementPolicy_STATUS: Interface augmentConversionForStorageAccountsManagementPolicy_Spec: Interface augmentConversionForStorageAccountsQueueService: Interface +augmentConversionForStorageAccountsQueueServiceOperatorSpec: Interface augmentConversionForStorageAccountsQueueService_STATUS: Interface augmentConversionForStorageAccountsQueueService_Spec: Interface augmentConversionForStorageAccountsQueueServicesQueue: Interface +augmentConversionForStorageAccountsQueueServicesQueueOperatorSpec: Interface augmentConversionForStorageAccountsQueueServicesQueue_STATUS: Interface augmentConversionForStorageAccountsQueueServicesQueue_Spec: Interface augmentConversionForStorageAccountsTableService: Interface +augmentConversionForStorageAccountsTableServiceOperatorSpec: Interface augmentConversionForStorageAccountsTableService_STATUS: Interface augmentConversionForStorageAccountsTableService_Spec: Interface augmentConversionForStorageAccountsTableServicesTable: Interface +augmentConversionForStorageAccountsTableServicesTableOperatorSpec: Interface augmentConversionForStorageAccountsTableServicesTable_STATUS: Interface augmentConversionForStorageAccountsTableServicesTable_Spec: Interface augmentConversionForTableAccessPolicy: Interface diff --git a/v2/api/storage/v1api20220901/storage/zz_generated.deepcopy.go b/v2/api/storage/v1api20220901/storage/zz_generated.deepcopy.go index e035ef7fb79..f82f7b1f00b 100644 --- a/v2/api/storage/v1api20220901/storage/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20220901/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -3758,6 +3759,17 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) @@ -3770,6 +3782,17 @@ func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -4335,6 +4358,50 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -4472,6 +4539,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4560,6 +4632,50 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -4741,6 +4857,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4829,6 +4950,50 @@ func (in *StorageAccountsFileServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopyInto(out *StorageAccountsFileServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServiceOperatorSpec. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopy() *StorageAccountsFileServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileService_STATUS) DeepCopyInto(out *StorageAccountsFileService_STATUS) { *out = *in @@ -4901,6 +5066,11 @@ func (in *StorageAccountsFileService_Spec) DeepCopyInto(out *StorageAccountsFile *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4994,6 +5164,50 @@ func (in *StorageAccountsFileServicesShareList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopyInto(out *StorageAccountsFileServicesShareOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServicesShareOperatorSpec. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopy() *StorageAccountsFileServicesShareOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServicesShareOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileServicesShare_STATUS) DeepCopyInto(out *StorageAccountsFileServicesShare_STATUS) { *out = *in @@ -5157,6 +5371,11 @@ func (in *StorageAccountsFileServicesShare_Spec) DeepCopyInto(out *StorageAccoun (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServicesShareOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5257,6 +5476,50 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -5314,6 +5577,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5402,6 +5670,50 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -5459,6 +5771,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5542,6 +5859,50 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -5608,6 +5969,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5691,6 +6057,50 @@ func (in *StorageAccountsTableServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopyInto(out *StorageAccountsTableServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServiceOperatorSpec. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopy() *StorageAccountsTableServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableService_STATUS) DeepCopyInto(out *StorageAccountsTableService_STATUS) { *out = *in @@ -5748,6 +6158,11 @@ func (in *StorageAccountsTableService_Spec) DeepCopyInto(out *StorageAccountsTab *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5831,6 +6246,50 @@ func (in *StorageAccountsTableServicesTableList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopyInto(out *StorageAccountsTableServicesTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServicesTableOperatorSpec. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopy() *StorageAccountsTableServicesTableOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServicesTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_STATUS) DeepCopyInto(out *StorageAccountsTableServicesTable_STATUS) { *out = *in @@ -5890,6 +6349,11 @@ func (in *StorageAccountsTableServicesTable_STATUS) DeepCopy() *StorageAccountsT // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_Spec) DeepCopyInto(out *StorageAccountsTableServicesTable_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServicesTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20220901/storage_account_types_gen.go b/v2/api/storage/v1api20220901/storage_account_types_gen.go index 47012d3ca48..b0db8d63dad 100644 --- a/v2/api/storage/v1api20220901/storage_account_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_account_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -111,6 +112,26 @@ func (account *StorageAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccount resource func (account *StorageAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &StorageAccount{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -304,18 +325,18 @@ func (account *StorageAccount) validateConfigMapDestinations() (admission.Warnin if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, - account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, - account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, - account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, - account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, - account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + var toValidate []*genruntime.ConfigMapDestination + if account.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, + account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, + account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, + account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, + account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, + account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -337,20 +358,20 @@ func (account *StorageAccount) validateSecretDestinations() (admission.Warnings, if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - account.Spec.OperatorSpec.Secrets.BlobEndpoint, - account.Spec.OperatorSpec.Secrets.DfsEndpoint, - account.Spec.OperatorSpec.Secrets.FileEndpoint, - account.Spec.OperatorSpec.Secrets.Key1, - account.Spec.OperatorSpec.Secrets.Key2, - account.Spec.OperatorSpec.Secrets.QueueEndpoint, - account.Spec.OperatorSpec.Secrets.TableEndpoint, - account.Spec.OperatorSpec.Secrets.WebEndpoint, + var toValidate []*genruntime.SecretDestination + if account.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + account.Spec.OperatorSpec.Secrets.BlobEndpoint, + account.Spec.OperatorSpec.Secrets.DfsEndpoint, + account.Spec.OperatorSpec.Secrets.FileEndpoint, + account.Spec.OperatorSpec.Secrets.Key1, + account.Spec.OperatorSpec.Secrets.Key2, + account.Spec.OperatorSpec.Secrets.QueueEndpoint, + account.Spec.OperatorSpec.Secrets.TableEndpoint, + account.Spec.OperatorSpec.Secrets.WebEndpoint, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -7146,9 +7167,15 @@ var storageAccount_Kind_STATUS_Values = map[string]StorageAccount_Kind_STATUS{ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } @@ -7156,6 +7183,24 @@ type StorageAccountOperatorSpec struct { // AssignProperties_From_StorageAccountOperatorSpec populates our StorageAccountOperatorSpec from the provided source StorageAccountOperatorSpec func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccountOperatorSpec(source *storage.StorageAccountOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap StorageAccountOperatorConfigMaps @@ -7168,6 +7213,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret StorageAccountOperatorSecrets @@ -7189,6 +7252,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.StorageAccountOperatorConfigMaps @@ -7201,6 +7282,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.StorageAccountOperatorSecrets diff --git a/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen.go index 9e724661c24..cd4b4e44e29 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsBlobService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobService resource func (service *StorageAccountsBlobService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsBlobService) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (service *StorageAccountsBlobService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsBlobService) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsBlobService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsBlobService) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsBlobService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsBlobService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobService) @@ -348,6 +393,10 @@ type StorageAccountsBlobService_Spec struct { // LastAccessTimeTrackingPolicy: The blob service property to configure last access time based tracking policy. LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -554,6 +603,8 @@ func (service *StorageAccountsBlobService_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -710,6 +761,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_From_StorageAcc service.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -818,6 +881,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_To_StorageAccou destination.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -2561,6 +2636,110 @@ func (properties *RestorePolicyProperties_STATUS) AssignProperties_To_RestorePol return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServiceOperatorSpec populates our StorageAccountsBlobServiceOperatorSpec from the provided source StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source *storage.StorageAccountsBlobServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServiceOperatorSpec populates the provided destination StorageAccountsBlobServiceOperatorSpec from our StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(destination *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Specifies a CORS rule for the Blob service. type CorsRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen_test.go index 5cbe45aa2bc..28f77db22a1 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_blob_service_types_gen_test.go @@ -1436,6 +1436,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServiceOperatorSpec to StorageAccountsBlobServiceOperatorSpec via AssignProperties_To_StorageAccountsBlobServiceOperatorSpec & AssignProperties_From_StorageAccountsBlobServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec tests if a specific instance of StorageAccountsBlobServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsBlobServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1685,5 +1782,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen.go index c7383637ae7..f4db684e344 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (container *StorageAccountsBlobServicesContainer) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobServicesContainer resource func (container *StorageAccountsBlobServicesContainer) defaultImpl() { container.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobServicesContainer{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (container *StorageAccountsBlobServicesContainer) ValidateUpdate(old runtim // createValidations validates the creation of the resource func (container *StorageAccountsBlobServicesContainer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference} + return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference, container.validateSecretDestinations, container.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (container *StorageAccountsBlobServicesContainer) updateValidations() []fun func(old runtime.Object) (admission.Warnings, error) { return container.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (container *StorageAccountsBlobServicesContainer) validateConfigMapDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(container, nil, container.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (container *StorageAccountsBlobServicesContainer) validateResourceReference return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (container *StorageAccountsBlobServicesContainer) validateSecretDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(container, nil, container.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (container *StorageAccountsBlobServicesContainer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobServicesContainer) @@ -354,6 +399,10 @@ type StorageAccountsBlobServicesContainer_Spec struct { // Metadata: A name-value pair to associate with the container as metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -501,6 +550,8 @@ func (container *StorageAccountsBlobServicesContainer_Spec) PopulateFromARM(owne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": container.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -620,6 +671,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_Fro // Metadata container.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServicesContainerOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -691,6 +754,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_To_ // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(container.Metadata) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServicesContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = container.OriginalVersion() @@ -2078,6 +2153,110 @@ func (properties *LegalHoldProperties_STATUS) AssignProperties_To_LegalHoldPrope return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec populates our StorageAccountsBlobServicesContainerOperatorSpec from the provided source StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec populates the provided destination StorageAccountsBlobServicesContainerOperatorSpec from our StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(destination *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ImmutabilityPolicyProperty_State_STATUS string const ( diff --git a/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen_test.go index dad750c99fc..182ada9ed15 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_blob_services_container_types_gen_test.go @@ -717,6 +717,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServicesContainerOperatorSpec to StorageAccountsBlobServicesContainerOperatorSpec via AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec & AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec tests if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsBlobServicesContainerOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -985,6 +1082,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen.go index ecc17d09eaa..7ad5956f78c 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsFileService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsFileService resource func (service *StorageAccountsFileService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsFileService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsFileService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsFileService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsFileService) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (service *StorageAccountsFileService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsFileService) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsFileService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsFileService) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsFileService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsFileService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsFileService) @@ -326,6 +371,10 @@ type StorageAccountsFileService_Spec struct { // File service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsFileServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -410,6 +459,8 @@ func (service *StorageAccountsFileService_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -513,6 +564,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_From_StorageAcc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -566,6 +629,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_To_StorageAccou destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -1113,6 +1188,110 @@ func (settings *ProtocolSettings_STATUS) AssignProperties_To_ProtocolSettings_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServiceOperatorSpec populates our StorageAccountsFileServiceOperatorSpec from the provided source StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source *storage.StorageAccountsFileServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServiceOperatorSpec populates the provided destination StorageAccountsFileServiceOperatorSpec from our StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_To_StorageAccountsFileServiceOperatorSpec(destination *storage.StorageAccountsFileServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Setting for SMB protocol type SmbSetting struct { // AuthenticationMethods: SMB authentication methods supported by server. Valid values are NTLMv2, Kerberos. Should be diff --git a/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen_test.go index 1bbdae76b47..b5002c34dc7 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_file_service_types_gen_test.go @@ -814,6 +814,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileService(gens map[string]g gens["Status"] = StorageAccountsFileService_STATUSGenerator() } +func Test_StorageAccountsFileServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServiceOperatorSpec to StorageAccountsFileServiceOperatorSpec via AssignProperties_To_StorageAccountsFileServiceOperatorSpec & AssignProperties_From_StorageAccountsFileServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec tests if a specific instance of StorageAccountsFileServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsFileServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServiceOperatorSpecGenerator() +var storageAccountsFileServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServiceOperatorSpecGenerator returns a generator of StorageAccountsFileServiceOperatorSpec instances for property testing. +func StorageAccountsFileServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServiceOperatorSpecGenerator != nil { + return storageAccountsFileServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServiceOperatorSpec{}), generators) + + return storageAccountsFileServiceOperatorSpecGenerator +} + func Test_StorageAccountsFileService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1037,6 +1134,7 @@ func StorageAccountsFileService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServiceOperatorSpecGenerator()) gens["ProtocolSettings"] = gen.PtrOf(ProtocolSettingsGenerator()) gens["ShareDeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen.go index 53137a4a983..b6b78881edb 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (share *StorageAccountsFileServicesShare) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsFileServicesShare resource func (share *StorageAccountsFileServicesShare) defaultImpl() { share.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsFileServicesShare{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (share *StorageAccountsFileServicesShare) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileServicesShare{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (share *StorageAccountsFileServicesShare) SecretDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileServicesShare{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (share *StorageAccountsFileServicesShare) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (share *StorageAccountsFileServicesShare) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){share.validateResourceReferences, share.validateOwnerReference} + return []func() (admission.Warnings, error){share.validateResourceReferences, share.validateOwnerReference, share.validateSecretDestinations, share.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (share *StorageAccountsFileServicesShare) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return share.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return share.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return share.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (share *StorageAccountsFileServicesShare) validateConfigMapDestinations() (admission.Warnings, error) { + if share.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(share, nil, share.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (share *StorageAccountsFileServicesShare) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (share *StorageAccountsFileServicesShare) validateSecretDestinations() (admission.Warnings, error) { + if share.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(share, nil, share.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (share *StorageAccountsFileServicesShare) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsFileServicesShare) @@ -346,6 +391,10 @@ type StorageAccountsFileServicesShare_Spec struct { // Metadata: A name-value pair to associate with the share as metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsFileServicesShareOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -472,6 +521,8 @@ func (share *StorageAccountsFileServicesShare_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": share.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -592,6 +643,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_From_Storag // Metadata share.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServicesShareOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + share.OperatorSpec = &operatorSpec + } else { + share.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -666,6 +729,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_To_StorageA // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(share.Metadata) + // OperatorSpec + if share.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServicesShareOperatorSpec + err := share.OperatorSpec.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = share.OriginalVersion() @@ -1714,6 +1789,110 @@ func (identifier *SignedIdentifier_STATUS) AssignProperties_To_SignedIdentifier_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServicesShareOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec populates our StorageAccountsFileServicesShareOperatorSpec from the provided source StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source *storage.StorageAccountsFileServicesShareOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec populates the provided destination StorageAccountsFileServicesShareOperatorSpec from our StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(destination *storage.StorageAccountsFileServicesShareOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AccessPolicy struct { // ExpiryTime: Expiry time of the access policy ExpiryTime *string `json:"expiryTime,omitempty"` diff --git a/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen_test.go index 8aba2533640..cf8b66ae364 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_file_services_share_types_gen_test.go @@ -594,6 +594,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare(gens map[st gens["Status"] = StorageAccountsFileServicesShare_STATUSGenerator() } +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServicesShareOperatorSpec to StorageAccountsFileServicesShareOperatorSpec via AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec & AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec tests if a specific instance of StorageAccountsFileServicesShareOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsFileServicesShareOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServicesShareOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServicesShareOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServicesShareOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServicesShareOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServicesShareOperatorSpecGenerator() +var storageAccountsFileServicesShareOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServicesShareOperatorSpecGenerator returns a generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing. +func StorageAccountsFileServicesShareOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServicesShareOperatorSpecGenerator != nil { + return storageAccountsFileServicesShareOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServicesShareOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServicesShareOperatorSpec{}), generators) + + return storageAccountsFileServicesShareOperatorSpecGenerator +} + func Test_StorageAccountsFileServicesShare_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -867,5 +964,6 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(ge // AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServicesShareOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(SignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen.go index 8dde68a1006..810802e5bc2 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (policy *StorageAccountsManagementPolicy) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsManagementPolicy resource func (policy *StorageAccountsManagementPolicy) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsManagementPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -205,7 +228,7 @@ func (policy *StorageAccountsManagementPolicy) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (policy *StorageAccountsManagementPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -223,7 +246,21 @@ func (policy *StorageAccountsManagementPolicy) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *StorageAccountsManagementPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -240,6 +277,14 @@ func (policy *StorageAccountsManagementPolicy) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *StorageAccountsManagementPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *StorageAccountsManagementPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsManagementPolicy) @@ -322,6 +367,10 @@ type StorageAccountsManagementPolicyList struct { } type StorageAccountsManagementPolicy_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -373,6 +422,8 @@ func (policy *StorageAccountsManagementPolicy_Spec) PopulateFromARM(owner genrun return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.StorageAccountsManagementPolicy_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -450,6 +501,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) ConvertSpecTo(destination ge // AssignProperties_From_StorageAccountsManagementPolicy_Spec populates our StorageAccountsManagementPolicy_Spec from the provided source StorageAccountsManagementPolicy_Spec func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_From_StorageAccountsManagementPolicy_Spec(source *storage.StorageAccountsManagementPolicy_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsManagementPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -479,6 +542,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_To_StorageA // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsManagementPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -937,6 +1012,110 @@ func (schema *ManagementPolicySchema_STATUS) AssignProperties_To_ManagementPolic return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec populates our StorageAccountsManagementPolicyOperatorSpec from the provided source StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source *storage.StorageAccountsManagementPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec populates the provided destination StorageAccountsManagementPolicyOperatorSpec from our StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(destination *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen_test.go index 8aa3fd4a3cb..62cffe20f44 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_management_policy_types_gen_test.go @@ -2353,6 +2353,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsManagementPolicyOperatorSpec to StorageAccountsManagementPolicyOperatorSpec via AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec & AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec tests if a specific instance of StorageAccountsManagementPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsManagementPolicyOperatorSpec + err := copied.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsManagementPolicyOperatorSpec + err = actual.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2573,6 +2670,7 @@ func StorageAccountsManagementPolicy_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen.go index 7d0a225441c..cdcb805ef76 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsQueueService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueService resource func (service *StorageAccountsQueueService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsQueueService) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (service *StorageAccountsQueueService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsQueueService) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsQueueService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsQueueService) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsQueueService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsQueueService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueService) @@ -326,6 +371,10 @@ type StorageAccountsQueueService_Spec struct { // Queue service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (service *StorageAccountsQueueService_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -461,6 +512,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -490,6 +553,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -710,6 +785,110 @@ func (service *StorageAccountsQueueService_STATUS) AssignProperties_To_StorageAc return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServiceOperatorSpec populates our StorageAccountsQueueServiceOperatorSpec from the provided source StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source *storage.StorageAccountsQueueServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServiceOperatorSpec populates the provided destination StorageAccountsQueueServiceOperatorSpec from our StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(destination *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen_test.go index c6c1dbd13ca..92ca9d801d7 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_queue_service_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServiceOperatorSpec to StorageAccountsQueueServiceOperatorSpec via AssignProperties_To_StorageAccountsQueueServiceOperatorSpec & AssignProperties_From_StorageAccountsQueueServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec tests if a specific instance of StorageAccountsQueueServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsQueueServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,4 +483,5 @@ func StorageAccountsQueueService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen.go index f72ed9667a3..da502d92dc7 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (queue *StorageAccountsQueueServicesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueServicesQueue resource func (queue *StorageAccountsQueueServicesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueServicesQueue{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (queue *StorageAccountsQueueServicesQueue) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (queue *StorageAccountsQueueServicesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (queue *StorageAccountsQueueServicesQueue) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *StorageAccountsQueueServicesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (queue *StorageAccountsQueueServicesQueue) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *StorageAccountsQueueServicesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *StorageAccountsQueueServicesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueServicesQueue) @@ -338,6 +383,10 @@ type StorageAccountsQueueServicesQueue_Spec struct { // Metadata: A name-value pair that represents queue metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -396,6 +445,8 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) PopulateFromARM(owner genru } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -465,6 +516,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_From_Stora // Metadata queue.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServicesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -488,6 +551,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_To_Storage // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(queue.Metadata) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServicesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -709,6 +784,110 @@ func (queue *StorageAccountsQueueServicesQueue_STATUS) AssignProperties_To_Stora return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec populates our StorageAccountsQueueServicesQueueOperatorSpec from the provided source StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec populates the provided destination StorageAccountsQueueServicesQueueOperatorSpec from our StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(destination *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen_test.go index d806c7b10f3..23c47e1338c 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_queue_services_queue_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServicesQueueOperatorSpec to StorageAccountsQueueServicesQueueOperatorSpec via AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec & AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec tests if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsQueueServicesQueueOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -361,6 +458,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -370,6 +470,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -380,3 +486,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen.go index c5e08e8b34a..d5e259d7f29 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -98,6 +101,26 @@ func (service *StorageAccountsTableService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsTableService resource func (service *StorageAccountsTableService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsTableService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsTableService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsTableService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableService{} // AzureName returns the Azure name of the resource (always "default") @@ -204,7 +227,7 @@ func (service *StorageAccountsTableService) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (service *StorageAccountsTableService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,21 @@ func (service *StorageAccountsTableService) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsTableService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -239,6 +276,14 @@ func (service *StorageAccountsTableService) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsTableService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsTableService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsTableService) @@ -326,6 +371,10 @@ type StorageAccountsTableService_Spec struct { // Table service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsTableServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -386,6 +435,8 @@ func (service *StorageAccountsTableService_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -461,6 +512,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -490,6 +553,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -710,6 +785,110 @@ func (service *StorageAccountsTableService_STATUS) AssignProperties_To_StorageAc return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServiceOperatorSpec populates our StorageAccountsTableServiceOperatorSpec from the provided source StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source *storage.StorageAccountsTableServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServiceOperatorSpec populates the provided destination StorageAccountsTableServiceOperatorSpec from our StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_To_StorageAccountsTableServiceOperatorSpec(destination *storage.StorageAccountsTableServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsTableService{}, &StorageAccountsTableServiceList{}) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen_test.go index e87d5cf0f2d..ee12d42224f 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_table_service_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableService(gens map[string] gens["Status"] = StorageAccountsTableService_STATUSGenerator() } +func Test_StorageAccountsTableServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServiceOperatorSpec to StorageAccountsTableServiceOperatorSpec via AssignProperties_To_StorageAccountsTableServiceOperatorSpec & AssignProperties_From_StorageAccountsTableServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec tests if a specific instance of StorageAccountsTableServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsTableServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServiceOperatorSpecGenerator() +var storageAccountsTableServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServiceOperatorSpecGenerator returns a generator of StorageAccountsTableServiceOperatorSpec instances for property testing. +func StorageAccountsTableServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServiceOperatorSpecGenerator != nil { + return storageAccountsTableServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServiceOperatorSpec{}), generators) + + return storageAccountsTableServiceOperatorSpecGenerator +} + func Test_StorageAccountsTableService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -386,4 +483,5 @@ func StorageAccountsTableService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen.go b/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen.go index 2d2a5db0233..ce38f3972c0 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen.go +++ b/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -105,6 +108,26 @@ func (table *StorageAccountsTableServicesTable) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsTableServicesTable resource func (table *StorageAccountsTableServicesTable) defaultImpl() { table.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsTableServicesTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *StorageAccountsTableServicesTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableServicesTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *StorageAccountsTableServicesTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableServicesTable{} // AzureName returns the Azure name of the resource @@ -212,7 +235,7 @@ func (table *StorageAccountsTableServicesTable) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (table *StorageAccountsTableServicesTable) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference} + return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference, table.validateSecretDestinations, table.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -230,7 +253,21 @@ func (table *StorageAccountsTableServicesTable) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return table.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (table *StorageAccountsTableServicesTable) validateConfigMapDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(table, nil, table.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -247,6 +284,14 @@ func (table *StorageAccountsTableServicesTable) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (table *StorageAccountsTableServicesTable) validateSecretDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(table, nil, table.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (table *StorageAccountsTableServicesTable) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsTableServicesTable) @@ -336,6 +381,10 @@ type StorageAccountsTableServicesTable_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsTableServicesTableOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -387,6 +436,8 @@ func (table *StorageAccountsTableServicesTable_Spec) PopulateFromARM(owner genru // Set property "AzureName": table.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": table.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -466,6 +517,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_From_Stora // AzureName table.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServicesTableOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + table.OperatorSpec = &operatorSpec + } else { + table.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -504,6 +567,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_To_Storage // AzureName destination.AzureName = table.AzureName + // OperatorSpec + if table.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServicesTableOperatorSpec + err := table.OperatorSpec.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = table.OriginalVersion() @@ -774,6 +849,110 @@ func (table *StorageAccountsTableServicesTable_STATUS) AssignProperties_To_Stora return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServicesTableOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec populates our StorageAccountsTableServicesTableOperatorSpec from the provided source StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source *storage.StorageAccountsTableServicesTableOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec populates the provided destination StorageAccountsTableServicesTableOperatorSpec from our StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(destination *storage.StorageAccountsTableServicesTableOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Object to set Table Access Policy. type TableSignedIdentifier struct { // AccessPolicy: Access policy diff --git a/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen_test.go b/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen_test.go index 1e6b3c23d9d..eaa3a6eb287 100644 --- a/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen_test.go +++ b/v2/api/storage/v1api20220901/storage_accounts_table_services_table_types_gen_test.go @@ -166,6 +166,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable(gens map[s gens["Status"] = StorageAccountsTableServicesTable_STATUSGenerator() } +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServicesTableOperatorSpec to StorageAccountsTableServicesTableOperatorSpec via AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec & AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec tests if a specific instance of StorageAccountsTableServicesTableOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other v20220901s.StorageAccountsTableServicesTableOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServicesTableOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServicesTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServicesTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServicesTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServicesTableOperatorSpecGenerator() +var storageAccountsTableServicesTableOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServicesTableOperatorSpecGenerator returns a generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing. +func StorageAccountsTableServicesTableOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServicesTableOperatorSpecGenerator != nil { + return storageAccountsTableServicesTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServicesTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServicesTableOperatorSpec{}), generators) + + return storageAccountsTableServicesTableOperatorSpecGenerator +} + func Test_StorageAccountsTableServicesTable_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -400,6 +497,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(g // AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServicesTableOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(TableSignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20220901/structure.txt b/v2/api/storage/v1api20220901/structure.txt index bb67534c504..0b66b6a399d 100644 --- a/v2/api/storage/v1api20220901/structure.txt +++ b/v2/api/storage/v1api20220901/structure.txt @@ -146,7 +146,8 @@ StorageAccount: Resource │ │ ├── "NetworkSourceDeleted" │ │ ├── "Provisioning" │ │ └── "Succeeded" -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (6 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -154,6 +155,7 @@ StorageAccount: Resource │ │ │ ├── QueueEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (8 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -469,7 +471,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: StorageAccount -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (2 properties) │ │ ├── Enabled: *bool @@ -511,6 +513,9 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *Enum (1 value) │ │ │ └── "AccessTimeTracking" │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RestorePolicy: *Object (2 properties) │ ├── Days: Validated<*int> (2 rules) @@ -577,7 +582,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: StorageAccountsBlobService -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 @@ -588,6 +593,9 @@ StorageAccountsBlobServicesContainer: Resource │ ├── ImmutableStorageWithVersioning: *Object (1 property) │ │ └── Enabled: *bool │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── PublicAccess: *Enum (3 values) │ ├── "Blob" @@ -666,7 +674,7 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsFileService: Resource ├── Owner: StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -682,6 +690,9 @@ StorageAccountsFileService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtocolSettings: *Object (1 property) │ │ └── Smb: *Object (5 properties) @@ -744,7 +755,7 @@ StorageAccountsFileService: Resource └── Type: *string StorageAccountsFileServicesShare: Resource ├── Owner: StorageAccountsFileService -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AccessTier: *Enum (4 values) │ │ ├── "Cool" │ │ ├── "Hot" @@ -757,6 +768,9 @@ StorageAccountsFileServicesShare: Resource │ │ ├── "NFS" │ │ └── "SMB" │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RootSquash: *Enum (3 values) │ │ ├── "AllSquash" @@ -820,7 +834,10 @@ StorageAccountsFileServicesShare: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Policy: *Object (1 property) │ └── Rules: Object (4 properties)[] @@ -1062,7 +1079,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -1078,6 +1095,9 @@ StorageAccountsQueueService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -1101,11 +1121,14 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: StorageAccountsQueueService -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (6 properties) ├── ApproximateMessageCount: *int @@ -1116,7 +1139,7 @@ StorageAccountsQueueServicesQueue: Resource └── Type: *string StorageAccountsTableService: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -1132,6 +1155,9 @@ StorageAccountsTableService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -1155,11 +1181,14 @@ StorageAccountsTableService: Resource └── Type: *string StorageAccountsTableServicesTable: Resource ├── Owner: StorageAccountsTableService -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ ├── Rule 1: MinLength: 3 │ │ └── Rule 2: Pattern: "^[A-Za-z][A-Za-z0-9]{2,62}$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── SignedIdentifiers: Object (2 properties)[] │ ├── AccessPolicy: *Object (3 properties) diff --git a/v2/api/storage/v1api20220901/zz_generated.deepcopy.go b/v2/api/storage/v1api20220901/zz_generated.deepcopy.go index d9b8d80b614..4118e92f8e3 100644 --- a/v2/api/storage/v1api20220901/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20220901/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220901 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -3084,11 +3085,33 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -3633,6 +3656,43 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -3763,6 +3823,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3844,6 +3909,43 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -4018,6 +4120,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4099,6 +4206,43 @@ func (in *StorageAccountsFileServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopyInto(out *StorageAccountsFileServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServiceOperatorSpec. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopy() *StorageAccountsFileServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileService_STATUS) DeepCopyInto(out *StorageAccountsFileService_STATUS) { *out = *in @@ -4164,6 +4308,11 @@ func (in *StorageAccountsFileService_Spec) DeepCopyInto(out *StorageAccountsFile *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4250,6 +4399,43 @@ func (in *StorageAccountsFileServicesShareList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopyInto(out *StorageAccountsFileServicesShareOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServicesShareOperatorSpec. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopy() *StorageAccountsFileServicesShareOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServicesShareOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileServicesShare_STATUS) DeepCopyInto(out *StorageAccountsFileServicesShare_STATUS) { *out = *in @@ -4406,6 +4592,11 @@ func (in *StorageAccountsFileServicesShare_Spec) DeepCopyInto(out *StorageAccoun (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServicesShareOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4499,6 +4690,43 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -4549,6 +4777,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4630,6 +4863,43 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -4680,6 +4950,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4756,6 +5031,43 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -4815,6 +5127,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4891,6 +5208,43 @@ func (in *StorageAccountsTableServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopyInto(out *StorageAccountsTableServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServiceOperatorSpec. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopy() *StorageAccountsTableServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableService_STATUS) DeepCopyInto(out *StorageAccountsTableService_STATUS) { *out = *in @@ -4941,6 +5295,11 @@ func (in *StorageAccountsTableService_Spec) DeepCopyInto(out *StorageAccountsTab *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5017,6 +5376,43 @@ func (in *StorageAccountsTableServicesTableList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopyInto(out *StorageAccountsTableServicesTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServicesTableOperatorSpec. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopy() *StorageAccountsTableServicesTableOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServicesTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_STATUS) DeepCopyInto(out *StorageAccountsTableServicesTable_STATUS) { *out = *in @@ -5069,6 +5465,11 @@ func (in *StorageAccountsTableServicesTable_STATUS) DeepCopy() *StorageAccountsT // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_Spec) DeepCopyInto(out *StorageAccountsTableServicesTable_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServicesTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20230101/storage/storage_account_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_account_types_gen.go index 6f65b350d17..27aaf5d0cf6 100644 --- a/v2/api/storage/v1api20230101/storage/storage_account_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_account_types_gen.go @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,26 @@ func (account *StorageAccount) SetConditions(conditions conditions.Conditions) { account.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &StorageAccount{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -594,9 +616,11 @@ type Sku_STATUS struct { // Storage version of v1api20230101.StorageAccountOperatorSpec // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { - ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` - PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` - Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } // Storage version of v1api20230101.StorageAccountSkuConversionStatus_STATUS diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen.go index fdda04cf439..2dee163051e 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (service *StorageAccountsBlobService) SetConditions(conditions conditions.C service.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobService{} // AzureName returns the Azure name of the resource (always "default") @@ -139,15 +162,16 @@ type StorageAccountsBlobServiceList struct { // Storage version of v1api20230101.StorageAccountsBlobService_Spec type StorageAccountsBlobService_Spec struct { - AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` - ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` - ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` - Cors *CorsRules `json:"cors,omitempty"` - DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` - DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` - IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` - LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AutomaticSnapshotPolicyEnabled *bool `json:"automaticSnapshotPolicyEnabled,omitempty"` + ChangeFeed *ChangeFeed `json:"changeFeed,omitempty"` + ContainerDeleteRetentionPolicy *DeleteRetentionPolicy `json:"containerDeleteRetentionPolicy,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + DefaultServiceVersion *string `json:"defaultServiceVersion,omitempty"` + DeleteRetentionPolicy *DeleteRetentionPolicy `json:"deleteRetentionPolicy,omitempty"` + IsVersioningEnabled *bool `json:"isVersioningEnabled,omitempty"` + LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -303,6 +327,14 @@ type RestorePolicyProperties_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20230101.StorageAccountsBlobServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.CorsRule // Specifies a CORS rule for the Blob service. type CorsRule struct { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen_test.go index fce47efe5f4..f784c2603a8 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_service_types_gen_test.go @@ -829,6 +829,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -995,5 +1050,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen.go index 01e2010e639..bfbda2bf4bf 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (container *StorageAccountsBlobServicesContainer) SetConditions(conditions container.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsBlobServicesContainer{} // AzureName returns the Azure name of the resource @@ -142,14 +165,15 @@ type StorageAccountsBlobServicesContainerList struct { type StorageAccountsBlobServicesContainer_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` - DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` - EnableNfsV3AllSquash *bool `json:"enableNfsV3AllSquash,omitempty"` - EnableNfsV3RootSquash *bool `json:"enableNfsV3RootSquash,omitempty"` - ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + DefaultEncryptionScope *string `json:"defaultEncryptionScope,omitempty"` + DenyEncryptionScopeOverride *bool `json:"denyEncryptionScopeOverride,omitempty"` + EnableNfsV3AllSquash *bool `json:"enableNfsV3AllSquash,omitempty"` + EnableNfsV3RootSquash *bool `json:"enableNfsV3RootSquash,omitempty"` + ImmutableStorageWithVersioning *ImmutableStorageWithVersioning `json:"immutableStorageWithVersioning,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -266,6 +290,14 @@ type LegalHoldProperties_STATUS struct { Tags []TagProperty_STATUS `json:"tags,omitempty"` } +// Storage version of v1api20230101.StorageAccountsBlobServicesContainerOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.ProtectedAppendWritesHistory_STATUS // Protected append writes history setting for the blob container with Legal holds. type ProtectedAppendWritesHistory_STATUS struct { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen_test.go index 10b03887e80..ceac2055e68 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_blob_services_container_types_gen_test.go @@ -420,6 +420,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -600,6 +655,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen.go index 85822ab51ed..e19153b5d34 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (service *StorageAccountsFileService) SetConditions(conditions conditions.C service.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsFileService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsFileService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsFileService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileService{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type StorageAccountsFileServiceList struct { // Storage version of v1api20230101.StorageAccountsFileService_Spec type StorageAccountsFileService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsFileServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -219,6 +243,14 @@ type ProtocolSettings_STATUS struct { Smb *SmbSetting_STATUS `json:"smb,omitempty"` } +// Storage version of v1api20230101.StorageAccountsFileServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.SmbSetting // Setting for SMB protocol type SmbSetting struct { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen_test.go index f2aab999061..5e4b9aa0a18 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_file_service_types_gen_test.go @@ -475,6 +475,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileService(gens map[string]g gens["Status"] = StorageAccountsFileService_STATUSGenerator() } +func Test_StorageAccountsFileServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServiceOperatorSpecGenerator() +var storageAccountsFileServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServiceOperatorSpecGenerator returns a generator of StorageAccountsFileServiceOperatorSpec instances for property testing. +func StorageAccountsFileServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServiceOperatorSpecGenerator != nil { + return storageAccountsFileServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServiceOperatorSpec{}), generators) + + return storageAccountsFileServiceOperatorSpecGenerator +} + func Test_StorageAccountsFileService_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -628,6 +683,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileService_Spec(gens map // AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServiceOperatorSpecGenerator()) gens["ProtocolSettings"] = gen.PtrOf(ProtocolSettingsGenerator()) gens["ShareDeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen.go index 6984e7a3b0e..2fc6ed78914 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (share *StorageAccountsFileServicesShare) SetConditions(conditions conditio share.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsFileServicesShare{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (share *StorageAccountsFileServicesShare) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileServicesShare{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (share *StorageAccountsFileServicesShare) SecretDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsFileServicesShare{} // AzureName returns the Azure name of the resource @@ -144,10 +167,11 @@ type StorageAccountsFileServicesShare_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - EnabledProtocols *string `json:"enabledProtocols,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + EnabledProtocols *string `json:"enabledProtocols,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsFileServicesShareOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -244,6 +268,14 @@ type SignedIdentifier_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20230101.StorageAccountsFileServicesShareOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServicesShareOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.AccessPolicy type AccessPolicy struct { ExpiryTime *string `json:"expiryTime,omitempty"` diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen_test.go index 27e97541c39..fb05fcb9d64 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_file_services_share_types_gen_test.go @@ -339,6 +339,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare(gens map[st gens["Status"] = StorageAccountsFileServicesShare_STATUSGenerator() } +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServicesShareOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServicesShareOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServicesShareOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServicesShareOperatorSpecGenerator() +var storageAccountsFileServicesShareOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServicesShareOperatorSpecGenerator returns a generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing. +func StorageAccountsFileServicesShareOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServicesShareOperatorSpecGenerator != nil { + return storageAccountsFileServicesShareOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServicesShareOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServicesShareOperatorSpec{}), generators) + + return storageAccountsFileServicesShareOperatorSpecGenerator +} + func Test_StorageAccountsFileServicesShare_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -516,5 +571,6 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(ge // AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServicesShareOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(SignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen.go index e4b5a7d84ed..10fa09762aa 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (policy *StorageAccountsManagementPolicy) SetConditions(conditions conditio policy.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsManagementPolicy{} // AzureName returns the Azure name of the resource (always "default") @@ -140,7 +163,8 @@ type StorageAccountsManagementPolicyList struct { // Storage version of v1api20230101.StorageAccountsManagementPolicy_Spec type StorageAccountsManagementPolicy_Spec struct { - OriginalVersion string `json:"originalVersion,omitempty"` + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -218,6 +242,14 @@ type ManagementPolicySchema_STATUS struct { Rules []ManagementPolicyRule_STATUS `json:"rules,omitempty"` } +// Storage version of v1api20230101.StorageAccountsManagementPolicyOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.ManagementPolicyRule // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen_test.go index 1704a2797d4..c12f7344fd4 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_management_policy_types_gen_test.go @@ -1426,6 +1426,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1576,6 +1631,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gen // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen.go index 0e225f82273..385a5465186 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (service *StorageAccountsQueueService) SetConditions(conditions conditions. service.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueService{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type StorageAccountsQueueServiceList struct { // Storage version of v1api20230101.StorageAccountsQueueService_Spec type StorageAccountsQueueService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -200,6 +224,14 @@ func (service *StorageAccountsQueueService_STATUS) ConvertStatusTo(destination g return destination.ConvertStatusFrom(service) } +// Storage version of v1api20230101.StorageAccountsQueueServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen_test.go index c72c766ec00..56e9b33e63d 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_service_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -229,4 +284,5 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueService_Spec(gens ma // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen.go index 9ebf7c2ab8e..61319d5de36 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (queue *StorageAccountsQueueServicesQueue) SetConditions(conditions conditi queue.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsQueueServicesQueue{} // AzureName returns the Azure name of the resource @@ -142,9 +165,10 @@ type StorageAccountsQueueServicesQueueList struct { type StorageAccountsQueueServicesQueue_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + Metadata map[string]string `json:"metadata,omitempty"` + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -205,6 +229,14 @@ func (queue *StorageAccountsQueueServicesQueue_STATUS) ConvertStatusTo(destinati return destination.ConvertStatusFrom(queue) } +// Storage version of v1api20230101.StorageAccountsQueueServicesQueueOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen_test.go index d002363192d..bc534c5c519 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_queue_services_queue_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -190,6 +245,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -199,6 +257,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -210,3 +274,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString()) gens["OriginalVersion"] = gen.AlphaString() } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen.go index 31263bc6148..45d04db72ea 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (service *StorageAccountsTableService) SetConditions(conditions conditions. service.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsTableService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsTableService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsTableService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableService{} // AzureName returns the Azure name of the resource (always "default") @@ -139,8 +162,9 @@ type StorageAccountsTableServiceList struct { // Storage version of v1api20230101.StorageAccountsTableService_Spec type StorageAccountsTableService_Spec struct { - Cors *CorsRules `json:"cors,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + Cors *CorsRules `json:"cors,omitempty"` + OperatorSpec *StorageAccountsTableServiceOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -200,6 +224,14 @@ func (service *StorageAccountsTableService_STATUS) ConvertStatusTo(destination g return destination.ConvertStatusFrom(service) } +// Storage version of v1api20230101.StorageAccountsTableServiceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServiceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&StorageAccountsTableService{}, &StorageAccountsTableServiceList{}) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen_test.go index 4e752b0afe5..0158271f40d 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_table_service_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableService(gens map[string] gens["Status"] = StorageAccountsTableService_STATUSGenerator() } +func Test_StorageAccountsTableServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServiceOperatorSpecGenerator() +var storageAccountsTableServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServiceOperatorSpecGenerator returns a generator of StorageAccountsTableServiceOperatorSpec instances for property testing. +func StorageAccountsTableServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServiceOperatorSpecGenerator != nil { + return storageAccountsTableServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServiceOperatorSpec{}), generators) + + return storageAccountsTableServiceOperatorSpecGenerator +} + func Test_StorageAccountsTableService_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -229,4 +284,5 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableService_Spec(gens ma // AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen.go b/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen.go index ae83951b356..ab23401936b 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (table *StorageAccountsTableServicesTable) SetConditions(conditions conditi table.Status.Conditions = conditions } +var _ configmaps.Exporter = &StorageAccountsTableServicesTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *StorageAccountsTableServicesTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableServicesTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *StorageAccountsTableServicesTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &StorageAccountsTableServicesTable{} // AzureName returns the Azure name of the resource @@ -142,8 +165,9 @@ type StorageAccountsTableServicesTableList struct { type StorageAccountsTableServicesTable_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + OperatorSpec *StorageAccountsTableServicesTableOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -205,6 +229,14 @@ func (table *StorageAccountsTableServicesTable_STATUS) ConvertStatusTo(destinati return destination.ConvertStatusFrom(table) } +// Storage version of v1api20230101.StorageAccountsTableServicesTableOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServicesTableOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20230101.TableSignedIdentifier // Object to set Table Access Policy. type TableSignedIdentifier struct { diff --git a/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen_test.go b/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen_test.go index 8b1a04cc290..62ec7f35858 100644 --- a/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage/storage_accounts_table_services_table_types_gen_test.go @@ -79,6 +79,61 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable(gens map[s gens["Status"] = StorageAccountsTableServicesTable_STATUSGenerator() } +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServicesTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServicesTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServicesTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServicesTableOperatorSpecGenerator() +var storageAccountsTableServicesTableOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServicesTableOperatorSpecGenerator returns a generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing. +func StorageAccountsTableServicesTableOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServicesTableOperatorSpecGenerator != nil { + return storageAccountsTableServicesTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServicesTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServicesTableOperatorSpec{}), generators) + + return storageAccountsTableServicesTableOperatorSpecGenerator +} + func Test_StorageAccountsTableServicesTable_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -230,6 +285,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(g // AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServicesTableOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(TableSignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage/structure.txt b/v2/api/storage/v1api20230101/storage/structure.txt index c6a30fe38e4..5ebadf36879 100644 --- a/v2/api/storage/v1api20230101/storage/structure.txt +++ b/v2/api/storage/v1api20230101/storage/structure.txt @@ -109,7 +109,8 @@ StorageAccount: Resource │ │ ├── PropertyBag: genruntime.PropertyBag │ │ ├── Reference: *genruntime.ResourceReference │ │ └── State: *string -│ ├── OperatorSpec: *Object (3 properties) +│ ├── OperatorSpec: *Object (5 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (7 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -119,6 +120,7 @@ StorageAccount: Resource │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination │ │ ├── PropertyBag: genruntime.PropertyBag +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (9 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -371,7 +373,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: storage/v1api20230101.StorageAccount -├── Spec: Object (12 properties) +├── Spec: Object (13 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (3 properties) │ │ ├── Enabled: *bool @@ -404,6 +406,10 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *string │ │ ├── PropertyBag: genruntime.PropertyBag │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -461,7 +467,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: storage/v1api20230101.StorageAccountsBlobService -├── Spec: Object (11 properties) +├── Spec: Object (12 properties) │ ├── AzureName: string │ ├── DefaultEncryptionScope: *string │ ├── DenyEncryptionScopeOverride: *bool @@ -471,6 +477,10 @@ StorageAccountsBlobServicesContainer: Resource │ │ ├── Enabled: *bool │ │ └── PropertyBag: genruntime.PropertyBag │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -536,7 +546,7 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsFileService: Resource ├── Owner: storage/v1api20230101.StorageAccount -├── Spec: Object (6 properties) +├── Spec: Object (7 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -546,6 +556,10 @@ StorageAccountsFileService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -602,11 +616,15 @@ StorageAccountsFileService: Resource └── Type: *string StorageAccountsFileServicesShare: Resource ├── Owner: storage/v1api20230101.StorageAccountsFileService -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AccessTier: *string │ ├── AzureName: string │ ├── EnabledProtocols: *string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -654,7 +672,11 @@ StorageAccountsFileServicesShare: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: storage/v1api20230101.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── Policy: *Object (2 properties) @@ -861,7 +883,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: storage/v1api20230101.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -871,6 +893,10 @@ StorageAccountsQueueService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -891,9 +917,13 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: storage/v1api20230101.StorageAccountsQueueService -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -907,7 +937,7 @@ StorageAccountsQueueServicesQueue: Resource └── Type: *string StorageAccountsTableService: Resource ├── Owner: storage/v1api20230101.StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (2 properties) │ │ ├── CorsRules: Object (6 properties)[] │ │ │ ├── AllowedHeaders: string[] @@ -917,6 +947,10 @@ StorageAccountsTableService: Resource │ │ │ ├── MaxAgeInSeconds: *int │ │ │ └── PropertyBag: genruntime.PropertyBag │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ └── PropertyBag: genruntime.PropertyBag @@ -937,8 +971,12 @@ StorageAccountsTableService: Resource └── Type: *string StorageAccountsTableServicesTable: Resource ├── Owner: storage/v1api20230101.StorageAccountsTableService -├── Spec: Object (5 properties) +├── Spec: Object (6 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/storage/v1api20230101/storage/zz_generated.deepcopy.go b/v2/api/storage/v1api20230101/storage/zz_generated.deepcopy.go index 118cf1bd165..7125d3cfde3 100644 --- a/v2/api/storage/v1api20230101/storage/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20230101/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -3773,6 +3774,17 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) @@ -3785,6 +3797,17 @@ func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSp (*out)[key] = val } } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -4360,6 +4383,50 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -4497,6 +4564,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4585,6 +4657,50 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -4766,6 +4882,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4854,6 +4975,50 @@ func (in *StorageAccountsFileServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopyInto(out *StorageAccountsFileServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServiceOperatorSpec. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopy() *StorageAccountsFileServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileService_STATUS) DeepCopyInto(out *StorageAccountsFileService_STATUS) { *out = *in @@ -4926,6 +5091,11 @@ func (in *StorageAccountsFileService_Spec) DeepCopyInto(out *StorageAccountsFile *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5019,6 +5189,50 @@ func (in *StorageAccountsFileServicesShareList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopyInto(out *StorageAccountsFileServicesShareOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServicesShareOperatorSpec. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopy() *StorageAccountsFileServicesShareOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServicesShareOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileServicesShare_STATUS) DeepCopyInto(out *StorageAccountsFileServicesShare_STATUS) { *out = *in @@ -5182,6 +5396,11 @@ func (in *StorageAccountsFileServicesShare_Spec) DeepCopyInto(out *StorageAccoun (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServicesShareOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5282,6 +5501,50 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -5339,6 +5602,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5427,6 +5695,50 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -5484,6 +5796,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5567,6 +5884,50 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -5633,6 +5994,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5716,6 +6082,50 @@ func (in *StorageAccountsTableServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopyInto(out *StorageAccountsTableServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServiceOperatorSpec. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopy() *StorageAccountsTableServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableService_STATUS) DeepCopyInto(out *StorageAccountsTableService_STATUS) { *out = *in @@ -5773,6 +6183,11 @@ func (in *StorageAccountsTableService_Spec) DeepCopyInto(out *StorageAccountsTab *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5856,6 +6271,50 @@ func (in *StorageAccountsTableServicesTableList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopyInto(out *StorageAccountsTableServicesTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServicesTableOperatorSpec. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopy() *StorageAccountsTableServicesTableOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServicesTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_STATUS) DeepCopyInto(out *StorageAccountsTableServicesTable_STATUS) { *out = *in @@ -5915,6 +6374,11 @@ func (in *StorageAccountsTableServicesTable_STATUS) DeepCopy() *StorageAccountsT // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_Spec) DeepCopyInto(out *StorageAccountsTableServicesTable_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServicesTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/storage/v1api20230101/storage_account_types_gen.go b/v2/api/storage/v1api20230101/storage_account_types_gen.go index b888e01e051..a83b39b4707 100644 --- a/v2/api/storage/v1api20230101/storage_account_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_account_types_gen.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -97,6 +98,26 @@ func (account *StorageAccount) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccount resource func (account *StorageAccount) defaultImpl() { account.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccount{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (account *StorageAccount) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccount{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (account *StorageAccount) SecretDestinationExpressions() []*core.DestinationExpression { + if account.Spec.OperatorSpec == nil { + return nil + } + return account.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccount{} // InitializeSpec initializes the spec for this resource from the given status @@ -301,18 +322,18 @@ func (account *StorageAccount) validateConfigMapDestinations() (admission.Warnin if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.ConfigMaps == nil { - return nil, nil - } - toValidate := []*genruntime.ConfigMapDestination{ - account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, - account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, - account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, - account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, - account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, - account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + var toValidate []*genruntime.ConfigMapDestination + if account.Spec.OperatorSpec.ConfigMaps != nil { + toValidate = []*genruntime.ConfigMapDestination{ + account.Spec.OperatorSpec.ConfigMaps.BlobEndpoint, + account.Spec.OperatorSpec.ConfigMaps.DfsEndpoint, + account.Spec.OperatorSpec.ConfigMaps.FileEndpoint, + account.Spec.OperatorSpec.ConfigMaps.QueueEndpoint, + account.Spec.OperatorSpec.ConfigMaps.TableEndpoint, + account.Spec.OperatorSpec.ConfigMaps.WebEndpoint, + } } - return configmaps.ValidateDestinations(toValidate) + return configmaps.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -334,20 +355,20 @@ func (account *StorageAccount) validateSecretDestinations() (admission.Warnings, if account.Spec.OperatorSpec == nil { return nil, nil } - if account.Spec.OperatorSpec.Secrets == nil { - return nil, nil - } - toValidate := []*genruntime.SecretDestination{ - account.Spec.OperatorSpec.Secrets.BlobEndpoint, - account.Spec.OperatorSpec.Secrets.DfsEndpoint, - account.Spec.OperatorSpec.Secrets.FileEndpoint, - account.Spec.OperatorSpec.Secrets.Key1, - account.Spec.OperatorSpec.Secrets.Key2, - account.Spec.OperatorSpec.Secrets.QueueEndpoint, - account.Spec.OperatorSpec.Secrets.TableEndpoint, - account.Spec.OperatorSpec.Secrets.WebEndpoint, + var toValidate []*genruntime.SecretDestination + if account.Spec.OperatorSpec.Secrets != nil { + toValidate = []*genruntime.SecretDestination{ + account.Spec.OperatorSpec.Secrets.BlobEndpoint, + account.Spec.OperatorSpec.Secrets.DfsEndpoint, + account.Spec.OperatorSpec.Secrets.FileEndpoint, + account.Spec.OperatorSpec.Secrets.Key1, + account.Spec.OperatorSpec.Secrets.Key2, + account.Spec.OperatorSpec.Secrets.QueueEndpoint, + account.Spec.OperatorSpec.Secrets.TableEndpoint, + account.Spec.OperatorSpec.Secrets.WebEndpoint, + } } - return secrets.ValidateDestinations(toValidate) + return secrets.ValidateDestinations(account, toValidate, account.Spec.OperatorSpec.SecretExpressions) } // validateWriteOnceProperties validates all WriteOnce properties @@ -7901,9 +7922,15 @@ var storageAccount_Kind_STATUS_Values = map[string]StorageAccount_Kind_STATUS{ // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type StorageAccountOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *StorageAccountOperatorConfigMaps `json:"configMaps,omitempty"` + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *StorageAccountOperatorSecrets `json:"secrets,omitempty"` } @@ -7911,6 +7938,24 @@ type StorageAccountOperatorSpec struct { // AssignProperties_From_StorageAccountOperatorSpec populates our StorageAccountOperatorSpec from the provided source StorageAccountOperatorSpec func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccountOperatorSpec(source *storage.StorageAccountOperatorSpec) error { + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + // ConfigMaps if source.ConfigMaps != nil { var configMap StorageAccountOperatorConfigMaps @@ -7923,6 +7968,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_From_StorageAccount operator.ConfigMaps = nil } + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + // Secrets if source.Secrets != nil { var secret StorageAccountOperatorSecrets @@ -7944,6 +8007,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + // ConfigMaps if operator.ConfigMaps != nil { var configMap storage.StorageAccountOperatorConfigMaps @@ -7956,6 +8037,24 @@ func (operator *StorageAccountOperatorSpec) AssignProperties_To_StorageAccountOp destination.ConfigMaps = nil } + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + // Secrets if operator.Secrets != nil { var secret storage.StorageAccountOperatorSecrets diff --git a/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen.go index 0a7547ae650..e5c60db49f3 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (service *StorageAccountsBlobService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobService resource func (service *StorageAccountsBlobService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsBlobService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsBlobService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsBlobService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsBlobService{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (service *StorageAccountsBlobService) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (service *StorageAccountsBlobService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (service *StorageAccountsBlobService) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsBlobService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (service *StorageAccountsBlobService) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsBlobService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsBlobService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobService) @@ -345,6 +390,10 @@ type StorageAccountsBlobService_Spec struct { // LastAccessTimeTrackingPolicy: The blob service property to configure last access time based tracking policy. LastAccessTimeTrackingPolicy *LastAccessTimeTrackingPolicy `json:"lastAccessTimeTrackingPolicy,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -551,6 +600,8 @@ func (service *StorageAccountsBlobService_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -707,6 +758,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_From_StorageAcc service.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -815,6 +878,18 @@ func (service *StorageAccountsBlobService_Spec) AssignProperties_To_StorageAccou destination.LastAccessTimeTrackingPolicy = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -2787,6 +2862,110 @@ func (properties *RestorePolicyProperties_STATUS) AssignProperties_To_RestorePol return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServiceOperatorSpec populates our StorageAccountsBlobServiceOperatorSpec from the provided source StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(source *storage.StorageAccountsBlobServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServiceOperatorSpec populates the provided destination StorageAccountsBlobServiceOperatorSpec from our StorageAccountsBlobServiceOperatorSpec +func (operator *StorageAccountsBlobServiceOperatorSpec) AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(destination *storage.StorageAccountsBlobServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Specifies a CORS rule for the Blob service. type CorsRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen_test.go index 2137335bfe2..cdd38d20c98 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_blob_service_types_gen_test.go @@ -1439,6 +1439,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService(gens map[string]g gens["Status"] = StorageAccountsBlobService_STATUSGenerator() } +func Test_StorageAccountsBlobServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServiceOperatorSpec to StorageAccountsBlobServiceOperatorSpec via AssignProperties_To_StorageAccountsBlobServiceOperatorSpec & AssignProperties_From_StorageAccountsBlobServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec tests if a specific instance of StorageAccountsBlobServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsBlobServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec, StorageAccountsBlobServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServiceOperatorSpec(subject StorageAccountsBlobServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServiceOperatorSpecGenerator() +var storageAccountsBlobServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServiceOperatorSpecGenerator returns a generator of StorageAccountsBlobServiceOperatorSpec instances for property testing. +func StorageAccountsBlobServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServiceOperatorSpecGenerator != nil { + return storageAccountsBlobServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServiceOperatorSpec{}), generators) + + return storageAccountsBlobServiceOperatorSpecGenerator +} + func Test_StorageAccountsBlobService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1688,5 +1785,6 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobService_Spec(gens map[str gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) gens["DeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) gens["LastAccessTimeTrackingPolicy"] = gen.PtrOf(LastAccessTimeTrackingPolicyGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServiceOperatorSpecGenerator()) gens["RestorePolicy"] = gen.PtrOf(RestorePolicyPropertiesGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen.go index 0b863e800ad..b478b37c4b8 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (container *StorageAccountsBlobServicesContainer) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsBlobServicesContainer resource func (container *StorageAccountsBlobServicesContainer) defaultImpl() { container.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsBlobServicesContainer{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (container *StorageAccountsBlobServicesContainer) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsBlobServicesContainer{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (container *StorageAccountsBlobServicesContainer) SecretDestinationExpressions() []*core.DestinationExpression { + if container.Spec.OperatorSpec == nil { + return nil + } + return container.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsBlobServicesContainer{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (container *StorageAccountsBlobServicesContainer) ValidateUpdate(old runtim // createValidations validates the creation of the resource func (container *StorageAccountsBlobServicesContainer) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference} + return []func() (admission.Warnings, error){container.validateResourceReferences, container.validateOwnerReference, container.validateSecretDestinations, container.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (container *StorageAccountsBlobServicesContainer) updateValidations() []fun func(old runtime.Object) (admission.Warnings, error) { return container.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return container.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (container *StorageAccountsBlobServicesContainer) validateConfigMapDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(container, nil, container.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (container *StorageAccountsBlobServicesContainer) validateResourceReference return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (container *StorageAccountsBlobServicesContainer) validateSecretDestinations() (admission.Warnings, error) { + if container.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(container, nil, container.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (container *StorageAccountsBlobServicesContainer) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsBlobServicesContainer) @@ -351,6 +396,10 @@ type StorageAccountsBlobServicesContainer_Spec struct { // Metadata: A name-value pair to associate with the container as metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsBlobServicesContainerOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -498,6 +547,8 @@ func (container *StorageAccountsBlobServicesContainer_Spec) PopulateFromARM(owne } } + // no assignment for property "OperatorSpec" + // Set property "Owner": container.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -617,6 +668,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_Fro // Metadata container.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsBlobServicesContainerOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + container.OperatorSpec = &operatorSpec + } else { + container.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -688,6 +751,18 @@ func (container *StorageAccountsBlobServicesContainer_Spec) AssignProperties_To_ // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(container.Metadata) + // OperatorSpec + if container.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsBlobServicesContainerOperatorSpec + err := container.OperatorSpec.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = container.OriginalVersion() @@ -2147,6 +2222,110 @@ func (properties *LegalHoldProperties_STATUS) AssignProperties_To_LegalHoldPrope return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsBlobServicesContainerOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec populates our StorageAccountsBlobServicesContainerOperatorSpec from the provided source StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(source *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec populates the provided destination StorageAccountsBlobServicesContainerOperatorSpec from our StorageAccountsBlobServicesContainerOperatorSpec +func (operator *StorageAccountsBlobServicesContainerOperatorSpec) AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(destination *storage.StorageAccountsBlobServicesContainerOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type ImmutabilityPolicyProperty_State_STATUS string const ( diff --git a/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen_test.go index 569be177d75..3fad7b6631e 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_blob_services_container_types_gen_test.go @@ -716,6 +716,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer(gens ma gens["Status"] = StorageAccountsBlobServicesContainer_STATUSGenerator() } +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsBlobServicesContainerOperatorSpec to StorageAccountsBlobServicesContainerOperatorSpec via AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec & AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec tests if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsBlobServicesContainerOperatorSpec + err := copied.AssignProperties_To_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = actual.AssignProperties_From_StorageAccountsBlobServicesContainerOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsBlobServicesContainerOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsBlobServicesContainerOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec, StorageAccountsBlobServicesContainerOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec runs a test to see if a specific instance of StorageAccountsBlobServicesContainerOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsBlobServicesContainerOperatorSpec(subject StorageAccountsBlobServicesContainerOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsBlobServicesContainerOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsBlobServicesContainerOperatorSpecGenerator() +var storageAccountsBlobServicesContainerOperatorSpecGenerator gopter.Gen + +// StorageAccountsBlobServicesContainerOperatorSpecGenerator returns a generator of StorageAccountsBlobServicesContainerOperatorSpec instances for property testing. +func StorageAccountsBlobServicesContainerOperatorSpecGenerator() gopter.Gen { + if storageAccountsBlobServicesContainerOperatorSpecGenerator != nil { + return storageAccountsBlobServicesContainerOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsBlobServicesContainerOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsBlobServicesContainerOperatorSpec{}), generators) + + return storageAccountsBlobServicesContainerOperatorSpecGenerator +} + func Test_StorageAccountsBlobServicesContainer_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -984,6 +1081,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spe // AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsBlobServicesContainer_Spec(gens map[string]gopter.Gen) { gens["ImmutableStorageWithVersioning"] = gen.PtrOf(ImmutableStorageWithVersioningGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsBlobServicesContainerOperatorSpecGenerator()) } func Test_TagProperty_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { diff --git a/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen.go index 2e75197450b..808d0aefd14 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (service *StorageAccountsFileService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsFileService resource func (service *StorageAccountsFileService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsFileService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsFileService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsFileService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsFileService{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (service *StorageAccountsFileService) ValidateUpdate(old runtime.Object) (a // createValidations validates the creation of the resource func (service *StorageAccountsFileService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (service *StorageAccountsFileService) updateValidations() []func(old runtim func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsFileService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (service *StorageAccountsFileService) validateResourceReferences() (admissi return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsFileService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsFileService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsFileService) @@ -323,6 +368,10 @@ type StorageAccountsFileService_Spec struct { // File service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsFileServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -407,6 +456,8 @@ func (service *StorageAccountsFileService_Spec) PopulateFromARM(owner genruntime } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -510,6 +561,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_From_StorageAcc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -563,6 +626,18 @@ func (service *StorageAccountsFileService_Spec) AssignProperties_To_StorageAccou destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -1172,6 +1247,110 @@ func (settings *ProtocolSettings_STATUS) AssignProperties_To_ProtocolSettings_ST return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServiceOperatorSpec populates our StorageAccountsFileServiceOperatorSpec from the provided source StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_From_StorageAccountsFileServiceOperatorSpec(source *storage.StorageAccountsFileServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServiceOperatorSpec populates the provided destination StorageAccountsFileServiceOperatorSpec from our StorageAccountsFileServiceOperatorSpec +func (operator *StorageAccountsFileServiceOperatorSpec) AssignProperties_To_StorageAccountsFileServiceOperatorSpec(destination *storage.StorageAccountsFileServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Setting for SMB protocol type SmbSetting struct { // AuthenticationMethods: SMB authentication methods supported by server. Valid values are NTLMv2, Kerberos. Should be diff --git a/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen_test.go index f4368546f50..7d906bd2e5d 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_file_service_types_gen_test.go @@ -813,6 +813,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileService(gens map[string]g gens["Status"] = StorageAccountsFileService_STATUSGenerator() } +func Test_StorageAccountsFileServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServiceOperatorSpec to StorageAccountsFileServiceOperatorSpec via AssignProperties_To_StorageAccountsFileServiceOperatorSpec & AssignProperties_From_StorageAccountsFileServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec tests if a specific instance of StorageAccountsFileServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsFileServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec, StorageAccountsFileServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServiceOperatorSpec(subject StorageAccountsFileServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServiceOperatorSpecGenerator() +var storageAccountsFileServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServiceOperatorSpecGenerator returns a generator of StorageAccountsFileServiceOperatorSpec instances for property testing. +func StorageAccountsFileServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServiceOperatorSpecGenerator != nil { + return storageAccountsFileServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServiceOperatorSpec{}), generators) + + return storageAccountsFileServiceOperatorSpecGenerator +} + func Test_StorageAccountsFileService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1036,6 +1133,7 @@ func StorageAccountsFileService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServiceOperatorSpecGenerator()) gens["ProtocolSettings"] = gen.PtrOf(ProtocolSettingsGenerator()) gens["ShareDeleteRetentionPolicy"] = gen.PtrOf(DeleteRetentionPolicyGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen.go index 91332357161..20cec2fc6b5 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (share *StorageAccountsFileServicesShare) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsFileServicesShare resource func (share *StorageAccountsFileServicesShare) defaultImpl() { share.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsFileServicesShare{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (share *StorageAccountsFileServicesShare) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsFileServicesShare{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (share *StorageAccountsFileServicesShare) SecretDestinationExpressions() []*core.DestinationExpression { + if share.Spec.OperatorSpec == nil { + return nil + } + return share.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsFileServicesShare{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (share *StorageAccountsFileServicesShare) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (share *StorageAccountsFileServicesShare) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){share.validateResourceReferences, share.validateOwnerReference} + return []func() (admission.Warnings, error){share.validateResourceReferences, share.validateOwnerReference, share.validateSecretDestinations, share.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (share *StorageAccountsFileServicesShare) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return share.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return share.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return share.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (share *StorageAccountsFileServicesShare) validateConfigMapDestinations() (admission.Warnings, error) { + if share.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(share, nil, share.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (share *StorageAccountsFileServicesShare) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (share *StorageAccountsFileServicesShare) validateSecretDestinations() (admission.Warnings, error) { + if share.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(share, nil, share.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (share *StorageAccountsFileServicesShare) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsFileServicesShare) @@ -343,6 +388,10 @@ type StorageAccountsFileServicesShare_Spec struct { // Metadata: A name-value pair to associate with the share as metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsFileServicesShareOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -469,6 +518,8 @@ func (share *StorageAccountsFileServicesShare_Spec) PopulateFromARM(owner genrun } } + // no assignment for property "OperatorSpec" + // Set property "Owner": share.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -589,6 +640,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_From_Storag // Metadata share.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsFileServicesShareOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + share.OperatorSpec = &operatorSpec + } else { + share.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -663,6 +726,18 @@ func (share *StorageAccountsFileServicesShare_Spec) AssignProperties_To_StorageA // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(share.Metadata) + // OperatorSpec + if share.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsFileServicesShareOperatorSpec + err := share.OperatorSpec.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = share.OriginalVersion() @@ -1798,6 +1873,110 @@ func (identifier *SignedIdentifier_STATUS) AssignProperties_To_SignedIdentifier_ return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsFileServicesShareOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec populates our StorageAccountsFileServicesShareOperatorSpec from the provided source StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(source *storage.StorageAccountsFileServicesShareOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec populates the provided destination StorageAccountsFileServicesShareOperatorSpec from our StorageAccountsFileServicesShareOperatorSpec +func (operator *StorageAccountsFileServicesShareOperatorSpec) AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(destination *storage.StorageAccountsFileServicesShareOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + type AccessPolicy struct { // ExpiryTime: Expiry time of the access policy ExpiryTime *string `json:"expiryTime,omitempty"` diff --git a/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen_test.go index 6d5ce73f893..06a4e425848 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_file_services_share_types_gen_test.go @@ -593,6 +593,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare(gens map[st gens["Status"] = StorageAccountsFileServicesShare_STATUSGenerator() } +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsFileServicesShareOperatorSpec to StorageAccountsFileServicesShareOperatorSpec via AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec & AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec tests if a specific instance of StorageAccountsFileServicesShareOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsFileServicesShareOperatorSpec + err := copied.AssignProperties_To_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsFileServicesShareOperatorSpec + err = actual.AssignProperties_From_StorageAccountsFileServicesShareOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsFileServicesShareOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsFileServicesShareOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec, StorageAccountsFileServicesShareOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec runs a test to see if a specific instance of StorageAccountsFileServicesShareOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsFileServicesShareOperatorSpec(subject StorageAccountsFileServicesShareOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsFileServicesShareOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsFileServicesShareOperatorSpecGenerator() +var storageAccountsFileServicesShareOperatorSpecGenerator gopter.Gen + +// StorageAccountsFileServicesShareOperatorSpecGenerator returns a generator of StorageAccountsFileServicesShareOperatorSpec instances for property testing. +func StorageAccountsFileServicesShareOperatorSpecGenerator() gopter.Gen { + if storageAccountsFileServicesShareOperatorSpecGenerator != nil { + return storageAccountsFileServicesShareOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsFileServicesShareOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsFileServicesShareOperatorSpec{}), generators) + + return storageAccountsFileServicesShareOperatorSpecGenerator +} + func Test_StorageAccountsFileServicesShare_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -866,5 +963,6 @@ func AddIndependentPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(ge // AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsFileServicesShare_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsFileServicesShareOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(SignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen.go index 30279369c8b..670082da976 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (policy *StorageAccountsManagementPolicy) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsManagementPolicy resource func (policy *StorageAccountsManagementPolicy) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsManagementPolicy{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (policy *StorageAccountsManagementPolicy) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsManagementPolicy{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (policy *StorageAccountsManagementPolicy) SecretDestinationExpressions() []*core.DestinationExpression { + if policy.Spec.OperatorSpec == nil { + return nil + } + return policy.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsManagementPolicy{} // InitializeSpec initializes the spec for this resource from the given status @@ -202,7 +225,7 @@ func (policy *StorageAccountsManagementPolicy) ValidateUpdate(old runtime.Object // createValidations validates the creation of the resource func (policy *StorageAccountsManagementPolicy) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference} + return []func() (admission.Warnings, error){policy.validateResourceReferences, policy.validateOwnerReference, policy.validateSecretDestinations, policy.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -220,7 +243,21 @@ func (policy *StorageAccountsManagementPolicy) updateValidations() []func(old ru func(old runtime.Object) (admission.Warnings, error) { return policy.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return policy.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (policy *StorageAccountsManagementPolicy) validateConfigMapDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -237,6 +274,14 @@ func (policy *StorageAccountsManagementPolicy) validateResourceReferences() (adm return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (policy *StorageAccountsManagementPolicy) validateSecretDestinations() (admission.Warnings, error) { + if policy.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(policy, nil, policy.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (policy *StorageAccountsManagementPolicy) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsManagementPolicy) @@ -319,6 +364,10 @@ type StorageAccountsManagementPolicyList struct { } type StorageAccountsManagementPolicy_Spec struct { + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsManagementPolicyOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -370,6 +419,8 @@ func (policy *StorageAccountsManagementPolicy_Spec) PopulateFromARM(owner genrun return fmt.Errorf("unexpected type supplied for PopulateFromARM() function. Expected arm.StorageAccountsManagementPolicy_Spec, got %T", armInput) } + // no assignment for property "OperatorSpec" + // Set property "Owner": policy.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -447,6 +498,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) ConvertSpecTo(destination ge // AssignProperties_From_StorageAccountsManagementPolicy_Spec populates our StorageAccountsManagementPolicy_Spec from the provided source StorageAccountsManagementPolicy_Spec func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_From_StorageAccountsManagementPolicy_Spec(source *storage.StorageAccountsManagementPolicy_Spec) error { + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsManagementPolicyOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + policy.OperatorSpec = &operatorSpec + } else { + policy.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -476,6 +539,18 @@ func (policy *StorageAccountsManagementPolicy_Spec) AssignProperties_To_StorageA // Create a new property bag propertyBag := genruntime.NewPropertyBag() + // OperatorSpec + if policy.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsManagementPolicyOperatorSpec + err := policy.OperatorSpec.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = policy.OriginalVersion() @@ -978,6 +1053,110 @@ func (schema *ManagementPolicySchema_STATUS) AssignProperties_To_ManagementPolic return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsManagementPolicyOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec populates our StorageAccountsManagementPolicyOperatorSpec from the provided source StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(source *storage.StorageAccountsManagementPolicyOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec populates the provided destination StorageAccountsManagementPolicyOperatorSpec from our StorageAccountsManagementPolicyOperatorSpec +func (operator *StorageAccountsManagementPolicyOperatorSpec) AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(destination *storage.StorageAccountsManagementPolicyOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // An object that wraps the Lifecycle rule. Each rule is uniquely defined by name. type ManagementPolicyRule struct { // +kubebuilder:validation:Required diff --git a/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen_test.go index 2a940b514b2..4a852f690c4 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_management_policy_types_gen_test.go @@ -2352,6 +2352,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy(gens map[str gens["Status"] = StorageAccountsManagementPolicy_STATUSGenerator() } +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsManagementPolicyOperatorSpec to StorageAccountsManagementPolicyOperatorSpec via AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec & AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec tests if a specific instance of StorageAccountsManagementPolicyOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsManagementPolicyOperatorSpec + err := copied.AssignProperties_To_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsManagementPolicyOperatorSpec + err = actual.AssignProperties_From_StorageAccountsManagementPolicyOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsManagementPolicyOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsManagementPolicyOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec, StorageAccountsManagementPolicyOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec runs a test to see if a specific instance of StorageAccountsManagementPolicyOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsManagementPolicyOperatorSpec(subject StorageAccountsManagementPolicyOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsManagementPolicyOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsManagementPolicyOperatorSpecGenerator() +var storageAccountsManagementPolicyOperatorSpecGenerator gopter.Gen + +// StorageAccountsManagementPolicyOperatorSpecGenerator returns a generator of StorageAccountsManagementPolicyOperatorSpec instances for property testing. +func StorageAccountsManagementPolicyOperatorSpecGenerator() gopter.Gen { + if storageAccountsManagementPolicyOperatorSpecGenerator != nil { + return storageAccountsManagementPolicyOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsManagementPolicyOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsManagementPolicyOperatorSpec{}), generators) + + return storageAccountsManagementPolicyOperatorSpecGenerator +} + func Test_StorageAccountsManagementPolicy_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -2572,6 +2669,7 @@ func StorageAccountsManagementPolicy_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsManagementPolicy_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsManagementPolicyOperatorSpecGenerator()) gens["Policy"] = gen.PtrOf(ManagementPolicySchemaGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen.go index 88815ad3c2e..40e05cdc1e9 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (service *StorageAccountsQueueService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueService resource func (service *StorageAccountsQueueService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsQueueService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsQueueService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsQueueService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsQueueService{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (service *StorageAccountsQueueService) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (service *StorageAccountsQueueService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (service *StorageAccountsQueueService) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsQueueService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (service *StorageAccountsQueueService) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsQueueService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsQueueService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueService) @@ -323,6 +368,10 @@ type StorageAccountsQueueService_Spec struct { // Queue service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -383,6 +432,8 @@ func (service *StorageAccountsQueueService_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -458,6 +509,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -487,6 +550,18 @@ func (service *StorageAccountsQueueService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -726,6 +801,110 @@ func (service *StorageAccountsQueueService_STATUS) AssignProperties_To_StorageAc return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServiceOperatorSpec populates our StorageAccountsQueueServiceOperatorSpec from the provided source StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(source *storage.StorageAccountsQueueServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServiceOperatorSpec populates the provided destination StorageAccountsQueueServiceOperatorSpec from our StorageAccountsQueueServiceOperatorSpec +func (operator *StorageAccountsQueueServiceOperatorSpec) AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(destination *storage.StorageAccountsQueueServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueService{}, &StorageAccountsQueueServiceList{}) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen_test.go index bc1ebbe0f70..19c5d597581 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_queue_service_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueService(gens map[string] gens["Status"] = StorageAccountsQueueService_STATUSGenerator() } +func Test_StorageAccountsQueueServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServiceOperatorSpec to StorageAccountsQueueServiceOperatorSpec via AssignProperties_To_StorageAccountsQueueServiceOperatorSpec & AssignProperties_From_StorageAccountsQueueServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec tests if a specific instance of StorageAccountsQueueServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsQueueServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec, StorageAccountsQueueServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServiceOperatorSpec(subject StorageAccountsQueueServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServiceOperatorSpecGenerator() +var storageAccountsQueueServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServiceOperatorSpecGenerator returns a generator of StorageAccountsQueueServiceOperatorSpec instances for property testing. +func StorageAccountsQueueServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServiceOperatorSpecGenerator != nil { + return storageAccountsQueueServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServiceOperatorSpec{}), generators) + + return storageAccountsQueueServiceOperatorSpecGenerator +} + func Test_StorageAccountsQueueService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,4 +482,5 @@ func StorageAccountsQueueService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsQueueService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen.go index fe668405ff4..eabd4fa04ee 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (queue *StorageAccountsQueueServicesQueue) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsQueueServicesQueue resource func (queue *StorageAccountsQueueServicesQueue) defaultImpl() { queue.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsQueueServicesQueue{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (queue *StorageAccountsQueueServicesQueue) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsQueueServicesQueue{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (queue *StorageAccountsQueueServicesQueue) SecretDestinationExpressions() []*core.DestinationExpression { + if queue.Spec.OperatorSpec == nil { + return nil + } + return queue.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsQueueServicesQueue{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (queue *StorageAccountsQueueServicesQueue) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (queue *StorageAccountsQueueServicesQueue) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference} + return []func() (admission.Warnings, error){queue.validateResourceReferences, queue.validateOwnerReference, queue.validateSecretDestinations, queue.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (queue *StorageAccountsQueueServicesQueue) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return queue.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return queue.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (queue *StorageAccountsQueueServicesQueue) validateConfigMapDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (queue *StorageAccountsQueueServicesQueue) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (queue *StorageAccountsQueueServicesQueue) validateSecretDestinations() (admission.Warnings, error) { + if queue.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(queue, nil, queue.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (queue *StorageAccountsQueueServicesQueue) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsQueueServicesQueue) @@ -335,6 +380,10 @@ type StorageAccountsQueueServicesQueue_Spec struct { // Metadata: A name-value pair that represents queue metadata. Metadata map[string]string `json:"metadata,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsQueueServicesQueueOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -393,6 +442,8 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) PopulateFromARM(owner genru } } + // no assignment for property "OperatorSpec" + // Set property "Owner": queue.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -462,6 +513,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_From_Stora // Metadata queue.Metadata = genruntime.CloneMapOfStringToString(source.Metadata) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsQueueServicesQueueOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + queue.OperatorSpec = &operatorSpec + } else { + queue.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -485,6 +548,18 @@ func (queue *StorageAccountsQueueServicesQueue_Spec) AssignProperties_To_Storage // Metadata destination.Metadata = genruntime.CloneMapOfStringToString(queue.Metadata) + // OperatorSpec + if queue.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsQueueServicesQueueOperatorSpec + err := queue.OperatorSpec.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = queue.OriginalVersion() @@ -716,6 +791,110 @@ func (queue *StorageAccountsQueueServicesQueue_STATUS) AssignProperties_To_Stora return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsQueueServicesQueueOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec populates our StorageAccountsQueueServicesQueueOperatorSpec from the provided source StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(source *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec populates the provided destination StorageAccountsQueueServicesQueueOperatorSpec from our StorageAccountsQueueServicesQueueOperatorSpec +func (operator *StorageAccountsQueueServicesQueueOperatorSpec) AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(destination *storage.StorageAccountsQueueServicesQueueOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsQueueServicesQueue{}, &StorageAccountsQueueServicesQueueList{}) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen_test.go index d69ac19e0e5..ae8f653c77c 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_queue_services_queue_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue(gens map[s gens["Status"] = StorageAccountsQueueServicesQueue_STATUSGenerator() } +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsQueueServicesQueueOperatorSpec to StorageAccountsQueueServicesQueueOperatorSpec via AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec & AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec tests if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsQueueServicesQueueOperatorSpec + err := copied.AssignProperties_To_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = actual.AssignProperties_From_StorageAccountsQueueServicesQueueOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsQueueServicesQueueOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsQueueServicesQueueOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec, StorageAccountsQueueServicesQueueOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec runs a test to see if a specific instance of StorageAccountsQueueServicesQueueOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsQueueServicesQueueOperatorSpec(subject StorageAccountsQueueServicesQueueOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsQueueServicesQueueOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsQueueServicesQueueOperatorSpecGenerator() +var storageAccountsQueueServicesQueueOperatorSpecGenerator gopter.Gen + +// StorageAccountsQueueServicesQueueOperatorSpecGenerator returns a generator of StorageAccountsQueueServicesQueueOperatorSpec instances for property testing. +func StorageAccountsQueueServicesQueueOperatorSpecGenerator() gopter.Gen { + if storageAccountsQueueServicesQueueOperatorSpecGenerator != nil { + return storageAccountsQueueServicesQueueOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsQueueServicesQueueOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueueOperatorSpec{}), generators) + + return storageAccountsQueueServicesQueueOperatorSpecGenerator +} + func Test_StorageAccountsQueueServicesQueue_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -360,6 +457,9 @@ func RunJSONSerializationTestForStorageAccountsQueueServicesQueue_Spec(subject S var storageAccountsQueueServicesQueue_SpecGenerator gopter.Gen // StorageAccountsQueueServicesQueue_SpecGenerator returns a generator of StorageAccountsQueueServicesQueue_Spec instances for property testing. +// We first initialize storageAccountsQueueServicesQueue_SpecGenerator with a simplified generator based on the +// fields with primitive types then replacing it with a more complex one that also handles complex fields +// to ensure any cycles in the object graph properly terminate. func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { if storageAccountsQueueServicesQueue_SpecGenerator != nil { return storageAccountsQueueServicesQueue_SpecGenerator @@ -369,6 +469,12 @@ func StorageAccountsQueueServicesQueue_SpecGenerator() gopter.Gen { AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + // The above call to gen.Struct() captures the map, so create a new one + generators = make(map[string]gopter.Gen) + AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(generators) + storageAccountsQueueServicesQueue_SpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsQueueServicesQueue_Spec{}), generators) + return storageAccountsQueueServicesQueue_SpecGenerator } @@ -379,3 +485,8 @@ func AddIndependentPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(g gen.AlphaString(), gen.AlphaString()) } + +// AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec is a factory method for creating gopter generators +func AddRelatedPropertyGeneratorsForStorageAccountsQueueServicesQueue_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsQueueServicesQueueOperatorSpecGenerator()) +} diff --git a/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen.go index 65964f67f5b..4ded6694a7a 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +87,26 @@ func (service *StorageAccountsTableService) Default() { // defaultImpl applies the code generated defaults to the StorageAccountsTableService resource func (service *StorageAccountsTableService) defaultImpl() {} +var _ configmaps.Exporter = &StorageAccountsTableService{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (service *StorageAccountsTableService) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableService{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (service *StorageAccountsTableService) SecretDestinationExpressions() []*core.DestinationExpression { + if service.Spec.OperatorSpec == nil { + return nil + } + return service.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsTableService{} // InitializeSpec initializes the spec for this resource from the given status @@ -201,7 +224,7 @@ func (service *StorageAccountsTableService) ValidateUpdate(old runtime.Object) ( // createValidations validates the creation of the resource func (service *StorageAccountsTableService) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference} + return []func() (admission.Warnings, error){service.validateResourceReferences, service.validateOwnerReference, service.validateSecretDestinations, service.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -219,7 +242,21 @@ func (service *StorageAccountsTableService) updateValidations() []func(old runti func(old runtime.Object) (admission.Warnings, error) { return service.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return service.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (service *StorageAccountsTableService) validateConfigMapDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(service, nil, service.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -236,6 +273,14 @@ func (service *StorageAccountsTableService) validateResourceReferences() (admiss return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (service *StorageAccountsTableService) validateSecretDestinations() (admission.Warnings, error) { + if service.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(service, nil, service.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (service *StorageAccountsTableService) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsTableService) @@ -323,6 +368,10 @@ type StorageAccountsTableService_Spec struct { // Table service. Cors *CorsRules `json:"cors,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsTableServiceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -383,6 +432,8 @@ func (service *StorageAccountsTableService_Spec) PopulateFromARM(owner genruntim } } + // no assignment for property "OperatorSpec" + // Set property "Owner": service.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -458,6 +509,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_From_StorageAc service.Cors = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServiceOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + service.OperatorSpec = &operatorSpec + } else { + service.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -487,6 +550,18 @@ func (service *StorageAccountsTableService_Spec) AssignProperties_To_StorageAcco destination.Cors = nil } + // OperatorSpec + if service.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServiceOperatorSpec + err := service.OperatorSpec.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServiceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = service.OriginalVersion() @@ -726,6 +801,110 @@ func (service *StorageAccountsTableService_STATUS) AssignProperties_To_StorageAc return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServiceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServiceOperatorSpec populates our StorageAccountsTableServiceOperatorSpec from the provided source StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_From_StorageAccountsTableServiceOperatorSpec(source *storage.StorageAccountsTableServiceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServiceOperatorSpec populates the provided destination StorageAccountsTableServiceOperatorSpec from our StorageAccountsTableServiceOperatorSpec +func (operator *StorageAccountsTableServiceOperatorSpec) AssignProperties_To_StorageAccountsTableServiceOperatorSpec(destination *storage.StorageAccountsTableServiceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&StorageAccountsTableService{}, &StorageAccountsTableServiceList{}) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen_test.go index aa288c61a82..8f0760259e5 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_table_service_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableService(gens map[string] gens["Status"] = StorageAccountsTableService_STATUSGenerator() } +func Test_StorageAccountsTableServiceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServiceOperatorSpec to StorageAccountsTableServiceOperatorSpec via AssignProperties_To_StorageAccountsTableServiceOperatorSpec & AssignProperties_From_StorageAccountsTableServiceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec tests if a specific instance of StorageAccountsTableServiceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsTableServiceOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServiceOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServiceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServiceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServiceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec, StorageAccountsTableServiceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServiceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServiceOperatorSpec(subject StorageAccountsTableServiceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServiceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServiceOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServiceOperatorSpecGenerator() +var storageAccountsTableServiceOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServiceOperatorSpecGenerator returns a generator of StorageAccountsTableServiceOperatorSpec instances for property testing. +func StorageAccountsTableServiceOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServiceOperatorSpecGenerator != nil { + return storageAccountsTableServiceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServiceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServiceOperatorSpec{}), generators) + + return storageAccountsTableServiceOperatorSpecGenerator +} + func Test_StorageAccountsTableService_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -385,4 +482,5 @@ func StorageAccountsTableService_SpecGenerator() gopter.Gen { // AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableService_Spec(gens map[string]gopter.Gen) { gens["Cors"] = gen.PtrOf(CorsRulesGenerator()) + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServiceOperatorSpecGenerator()) } diff --git a/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen.go b/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen.go index 7543832b06b..635b973d9cc 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen.go +++ b/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (table *StorageAccountsTableServicesTable) defaultAzureName() { // defaultImpl applies the code generated defaults to the StorageAccountsTableServicesTable resource func (table *StorageAccountsTableServicesTable) defaultImpl() { table.defaultAzureName() } +var _ configmaps.Exporter = &StorageAccountsTableServicesTable{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (table *StorageAccountsTableServicesTable) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &StorageAccountsTableServicesTable{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (table *StorageAccountsTableServicesTable) SecretDestinationExpressions() []*core.DestinationExpression { + if table.Spec.OperatorSpec == nil { + return nil + } + return table.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &StorageAccountsTableServicesTable{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (table *StorageAccountsTableServicesTable) ValidateUpdate(old runtime.Objec // createValidations validates the creation of the resource func (table *StorageAccountsTableServicesTable) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference} + return []func() (admission.Warnings, error){table.validateResourceReferences, table.validateOwnerReference, table.validateSecretDestinations, table.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (table *StorageAccountsTableServicesTable) updateValidations() []func(old r func(old runtime.Object) (admission.Warnings, error) { return table.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return table.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (table *StorageAccountsTableServicesTable) validateConfigMapDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(table, nil, table.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (table *StorageAccountsTableServicesTable) validateResourceReferences() (ad return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (table *StorageAccountsTableServicesTable) validateSecretDestinations() (admission.Warnings, error) { + if table.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(table, nil, table.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (table *StorageAccountsTableServicesTable) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*StorageAccountsTableServicesTable) @@ -333,6 +378,10 @@ type StorageAccountsTableServicesTable_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *StorageAccountsTableServicesTableOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -384,6 +433,8 @@ func (table *StorageAccountsTableServicesTable_Spec) PopulateFromARM(owner genru // Set property "AzureName": table.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": table.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -463,6 +514,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_From_Stora // AzureName table.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec StorageAccountsTableServicesTableOperatorSpec + err := operatorSpec.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + table.OperatorSpec = &operatorSpec + } else { + table.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -501,6 +564,18 @@ func (table *StorageAccountsTableServicesTable_Spec) AssignProperties_To_Storage // AzureName destination.AzureName = table.AzureName + // OperatorSpec + if table.OperatorSpec != nil { + var operatorSpec storage.StorageAccountsTableServicesTableOperatorSpec + err := table.OperatorSpec.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = table.OriginalVersion() @@ -796,6 +871,110 @@ func (table *StorageAccountsTableServicesTable_STATUS) AssignProperties_To_Stora return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type StorageAccountsTableServicesTableOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec populates our StorageAccountsTableServicesTableOperatorSpec from the provided source StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(source *storage.StorageAccountsTableServicesTableOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec populates the provided destination StorageAccountsTableServicesTableOperatorSpec from our StorageAccountsTableServicesTableOperatorSpec +func (operator *StorageAccountsTableServicesTableOperatorSpec) AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(destination *storage.StorageAccountsTableServicesTableOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Object to set Table Access Policy. type TableSignedIdentifier struct { // AccessPolicy: Access policy diff --git a/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen_test.go b/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen_test.go index 89d82cf62e6..2d3505269ec 100644 --- a/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen_test.go +++ b/v2/api/storage/v1api20230101/storage_accounts_table_services_table_types_gen_test.go @@ -165,6 +165,103 @@ func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable(gens map[s gens["Status"] = StorageAccountsTableServicesTable_STATUSGenerator() } +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from StorageAccountsTableServicesTableOperatorSpec to StorageAccountsTableServicesTableOperatorSpec via AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec & AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec tests if a specific instance of StorageAccountsTableServicesTableOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.StorageAccountsTableServicesTableOperatorSpec + err := copied.AssignProperties_To_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual StorageAccountsTableServicesTableOperatorSpec + err = actual.AssignProperties_From_StorageAccountsTableServicesTableOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_StorageAccountsTableServicesTableOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of StorageAccountsTableServicesTableOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec, StorageAccountsTableServicesTableOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec runs a test to see if a specific instance of StorageAccountsTableServicesTableOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForStorageAccountsTableServicesTableOperatorSpec(subject StorageAccountsTableServicesTableOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual StorageAccountsTableServicesTableOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing - lazily instantiated by +// StorageAccountsTableServicesTableOperatorSpecGenerator() +var storageAccountsTableServicesTableOperatorSpecGenerator gopter.Gen + +// StorageAccountsTableServicesTableOperatorSpecGenerator returns a generator of StorageAccountsTableServicesTableOperatorSpec instances for property testing. +func StorageAccountsTableServicesTableOperatorSpecGenerator() gopter.Gen { + if storageAccountsTableServicesTableOperatorSpecGenerator != nil { + return storageAccountsTableServicesTableOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + storageAccountsTableServicesTableOperatorSpecGenerator = gen.Struct(reflect.TypeOf(StorageAccountsTableServicesTableOperatorSpec{}), generators) + + return storageAccountsTableServicesTableOperatorSpecGenerator +} + func Test_StorageAccountsTableServicesTable_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -399,6 +496,7 @@ func AddIndependentPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(g // AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForStorageAccountsTableServicesTable_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(StorageAccountsTableServicesTableOperatorSpecGenerator()) gens["SignedIdentifiers"] = gen.SliceOf(TableSignedIdentifierGenerator()) } diff --git a/v2/api/storage/v1api20230101/structure.txt b/v2/api/storage/v1api20230101/structure.txt index fa5085b2530..5a3fdca737c 100644 --- a/v2/api/storage/v1api20230101/structure.txt +++ b/v2/api/storage/v1api20230101/structure.txt @@ -147,7 +147,8 @@ StorageAccount: Resource │ │ ├── "NetworkSourceDeleted" │ │ ├── "Provisioning" │ │ └── "Succeeded" -│ ├── OperatorSpec: *Object (2 properties) +│ ├── OperatorSpec: *Object (4 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] │ │ ├── ConfigMaps: *Object (6 properties) │ │ │ ├── BlobEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── DfsEndpoint: *genruntime.ConfigMapDestination @@ -155,6 +156,7 @@ StorageAccount: Resource │ │ │ ├── QueueEndpoint: *genruntime.ConfigMapDestination │ │ │ ├── TableEndpoint: *genruntime.ConfigMapDestination │ │ │ └── WebEndpoint: *genruntime.ConfigMapDestination +│ │ ├── SecretExpressions: *core.DestinationExpression[] │ │ └── Secrets: *Object (8 properties) │ │ ├── BlobEndpoint: *genruntime.SecretDestination │ │ ├── DfsEndpoint: *genruntime.SecretDestination @@ -481,7 +483,7 @@ StorageAccount: Resource └── Type: *string StorageAccountsBlobService: Resource ├── Owner: StorageAccount -├── Spec: Object (10 properties) +├── Spec: Object (11 properties) │ ├── AutomaticSnapshotPolicyEnabled: *bool │ ├── ChangeFeed: *Object (2 properties) │ │ ├── Enabled: *bool @@ -525,6 +527,9 @@ StorageAccountsBlobService: Resource │ │ ├── Name: *Enum (1 value) │ │ │ └── "AccessTimeTracking" │ │ └── TrackingGranularityInDays: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── RestorePolicy: *Object (2 properties) │ ├── Days: Validated<*int> (2 rules) @@ -593,7 +598,7 @@ StorageAccountsBlobService: Resource └── Type: *string StorageAccountsBlobServicesContainer: Resource ├── Owner: StorageAccountsBlobService -├── Spec: Object (9 properties) +├── Spec: Object (10 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 @@ -604,6 +609,9 @@ StorageAccountsBlobServicesContainer: Resource │ ├── ImmutableStorageWithVersioning: *Object (1 property) │ │ └── Enabled: *bool │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── PublicAccess: *Enum (3 values) │ ├── "Blob" @@ -682,7 +690,7 @@ StorageAccountsBlobServicesContainer: Resource └── Version: *string StorageAccountsFileService: Resource ├── Owner: StorageAccount -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -700,6 +708,9 @@ StorageAccountsFileService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProtocolSettings: *Object (1 property) │ │ └── Smb: *Object (5 properties) @@ -764,7 +775,7 @@ StorageAccountsFileService: Resource └── Type: *string StorageAccountsFileServicesShare: Resource ├── Owner: StorageAccountsFileService -├── Spec: Object (8 properties) +├── Spec: Object (9 properties) │ ├── AccessTier: *Enum (4 values) │ │ ├── "Cool" │ │ ├── "Hot" @@ -777,6 +788,9 @@ StorageAccountsFileServicesShare: Resource │ │ ├── "NFS" │ │ └── "SMB" │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── RootSquash: *Enum (3 values) │ │ ├── "AllSquash" @@ -840,7 +854,10 @@ StorageAccountsFileServicesShare: Resource └── Version: *string StorageAccountsManagementPolicy: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── Policy: *Object (1 property) │ └── Rules: Object (4 properties)[] @@ -1082,7 +1099,7 @@ StorageAccountsManagementPolicy: Resource └── Type: *string StorageAccountsQueueService: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -1100,6 +1117,9 @@ StorageAccountsQueueService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -1125,11 +1145,14 @@ StorageAccountsQueueService: Resource └── Type: *string StorageAccountsQueueServicesQueue: Resource ├── Owner: StorageAccountsQueueService -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (2 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ └── Rule 1: MinLength: 3 │ ├── Metadata: map[string]string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (6 properties) ├── ApproximateMessageCount: *int @@ -1140,7 +1163,7 @@ StorageAccountsQueueServicesQueue: Resource └── Type: *string StorageAccountsTableService: Resource ├── Owner: StorageAccount -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── Cors: *Object (1 property) │ │ └── CorsRules: Object (5 properties)[] │ │ ├── AllowedHeaders: string[] @@ -1158,6 +1181,9 @@ StorageAccountsTableService: Resource │ │ ├── AllowedOrigins: string[] │ │ ├── ExposedHeaders: string[] │ │ └── MaxAgeInSeconds: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Owner: *genruntime.KnownResourceReference └── Status: Object (5 properties) ├── Conditions: conditions.Condition[] @@ -1183,11 +1209,14 @@ StorageAccountsTableService: Resource └── Type: *string StorageAccountsTableServicesTable: Resource ├── Owner: StorageAccountsTableService -├── Spec: Object (3 properties) +├── Spec: Object (4 properties) │ ├── AzureName: Validated (3 rules) │ │ ├── Rule 0: MaxLength: 63 │ │ ├── Rule 1: MinLength: 3 │ │ └── Rule 2: Pattern: "^[A-Za-z][A-Za-z0-9]{2,62}$" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ └── SignedIdentifiers: Object (2 properties)[] │ ├── AccessPolicy: *Object (3 properties) diff --git a/v2/api/storage/v1api20230101/zz_generated.deepcopy.go b/v2/api/storage/v1api20230101/zz_generated.deepcopy.go index ac2003d4d5c..6183a1f4774 100644 --- a/v2/api/storage/v1api20230101/zz_generated.deepcopy.go +++ b/v2/api/storage/v1api20230101/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20230101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -3099,11 +3100,33 @@ func (in *StorageAccountOperatorSecrets) DeepCopy() *StorageAccountOperatorSecre // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountOperatorSpec) DeepCopyInto(out *StorageAccountOperatorSpec) { *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.ConfigMaps != nil { in, out := &in.ConfigMaps, &out.ConfigMaps *out = new(StorageAccountOperatorConfigMaps) (*in).DeepCopyInto(*out) } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } if in.Secrets != nil { in, out := &in.Secrets, &out.Secrets *out = new(StorageAccountOperatorSecrets) @@ -3658,6 +3681,43 @@ func (in *StorageAccountsBlobServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServiceOperatorSpec. +func (in *StorageAccountsBlobServiceOperatorSpec) DeepCopy() *StorageAccountsBlobServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobService_STATUS) DeepCopyInto(out *StorageAccountsBlobService_STATUS) { *out = *in @@ -3788,6 +3848,11 @@ func (in *StorageAccountsBlobService_Spec) DeepCopyInto(out *StorageAccountsBlob *out = new(LastAccessTimeTrackingPolicy) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3869,6 +3934,43 @@ func (in *StorageAccountsBlobServicesContainerList) DeepCopyObject() runtime.Obj return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopyInto(out *StorageAccountsBlobServicesContainerOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsBlobServicesContainerOperatorSpec. +func (in *StorageAccountsBlobServicesContainerOperatorSpec) DeepCopy() *StorageAccountsBlobServicesContainerOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsBlobServicesContainerOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsBlobServicesContainer_STATUS) DeepCopyInto(out *StorageAccountsBlobServicesContainer_STATUS) { *out = *in @@ -4043,6 +4145,11 @@ func (in *StorageAccountsBlobServicesContainer_Spec) DeepCopyInto(out *StorageAc (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsBlobServicesContainerOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4124,6 +4231,43 @@ func (in *StorageAccountsFileServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopyInto(out *StorageAccountsFileServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServiceOperatorSpec. +func (in *StorageAccountsFileServiceOperatorSpec) DeepCopy() *StorageAccountsFileServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileService_STATUS) DeepCopyInto(out *StorageAccountsFileService_STATUS) { *out = *in @@ -4189,6 +4333,11 @@ func (in *StorageAccountsFileService_Spec) DeepCopyInto(out *StorageAccountsFile *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4275,6 +4424,43 @@ func (in *StorageAccountsFileServicesShareList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopyInto(out *StorageAccountsFileServicesShareOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsFileServicesShareOperatorSpec. +func (in *StorageAccountsFileServicesShareOperatorSpec) DeepCopy() *StorageAccountsFileServicesShareOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsFileServicesShareOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsFileServicesShare_STATUS) DeepCopyInto(out *StorageAccountsFileServicesShare_STATUS) { *out = *in @@ -4431,6 +4617,11 @@ func (in *StorageAccountsFileServicesShare_Spec) DeepCopyInto(out *StorageAccoun (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsFileServicesShareOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4524,6 +4715,43 @@ func (in *StorageAccountsManagementPolicyList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopyInto(out *StorageAccountsManagementPolicyOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsManagementPolicyOperatorSpec. +func (in *StorageAccountsManagementPolicyOperatorSpec) DeepCopy() *StorageAccountsManagementPolicyOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsManagementPolicyOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_STATUS) DeepCopyInto(out *StorageAccountsManagementPolicy_STATUS) { *out = *in @@ -4574,6 +4802,11 @@ func (in *StorageAccountsManagementPolicy_STATUS) DeepCopy() *StorageAccountsMan // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsManagementPolicy_Spec) DeepCopyInto(out *StorageAccountsManagementPolicy_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsManagementPolicyOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4655,6 +4888,43 @@ func (in *StorageAccountsQueueServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServiceOperatorSpec. +func (in *StorageAccountsQueueServiceOperatorSpec) DeepCopy() *StorageAccountsQueueServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueService_STATUS) DeepCopyInto(out *StorageAccountsQueueService_STATUS) { *out = *in @@ -4705,6 +4975,11 @@ func (in *StorageAccountsQueueService_Spec) DeepCopyInto(out *StorageAccountsQue *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4781,6 +5056,43 @@ func (in *StorageAccountsQueueServicesQueueList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopyInto(out *StorageAccountsQueueServicesQueueOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsQueueServicesQueueOperatorSpec. +func (in *StorageAccountsQueueServicesQueueOperatorSpec) DeepCopy() *StorageAccountsQueueServicesQueueOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsQueueServicesQueueOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsQueueServicesQueue_STATUS) DeepCopyInto(out *StorageAccountsQueueServicesQueue_STATUS) { *out = *in @@ -4840,6 +5152,11 @@ func (in *StorageAccountsQueueServicesQueue_Spec) DeepCopyInto(out *StorageAccou (*out)[key] = val } } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsQueueServicesQueueOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -4916,6 +5233,43 @@ func (in *StorageAccountsTableServiceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopyInto(out *StorageAccountsTableServiceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServiceOperatorSpec. +func (in *StorageAccountsTableServiceOperatorSpec) DeepCopy() *StorageAccountsTableServiceOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServiceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableService_STATUS) DeepCopyInto(out *StorageAccountsTableService_STATUS) { *out = *in @@ -4966,6 +5320,11 @@ func (in *StorageAccountsTableService_Spec) DeepCopyInto(out *StorageAccountsTab *out = new(CorsRules) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServiceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -5042,6 +5401,43 @@ func (in *StorageAccountsTableServicesTableList) DeepCopyObject() runtime.Object return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopyInto(out *StorageAccountsTableServicesTableOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageAccountsTableServicesTableOperatorSpec. +func (in *StorageAccountsTableServicesTableOperatorSpec) DeepCopy() *StorageAccountsTableServicesTableOperatorSpec { + if in == nil { + return nil + } + out := new(StorageAccountsTableServicesTableOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_STATUS) DeepCopyInto(out *StorageAccountsTableServicesTable_STATUS) { *out = *in @@ -5094,6 +5490,11 @@ func (in *StorageAccountsTableServicesTable_STATUS) DeepCopy() *StorageAccountsT // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StorageAccountsTableServicesTable_Spec) DeepCopyInto(out *StorageAccountsTableServicesTable_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(StorageAccountsTableServicesTableOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/subscription/v1api20211001/alias_types_gen.go b/v2/api/subscription/v1api20211001/alias_types_gen.go index c0231177e0c..48c17c0cffc 100644 --- a/v2/api/subscription/v1api20211001/alias_types_gen.go +++ b/v2/api/subscription/v1api20211001/alias_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (alias *Alias) defaultAzureName() { // defaultImpl applies the code generated defaults to the Alias resource func (alias *Alias) defaultImpl() { alias.defaultAzureName() } +var _ configmaps.Exporter = &Alias{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (alias *Alias) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if alias.Spec.OperatorSpec == nil { + return nil + } + return alias.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Alias{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (alias *Alias) SecretDestinationExpressions() []*core.DestinationExpression { + if alias.Spec.OperatorSpec == nil { + return nil + } + return alias.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Alias{} // InitializeSpec initializes the spec for this resource from the given status @@ -208,7 +231,7 @@ func (alias *Alias) ValidateUpdate(old runtime.Object) (admission.Warnings, erro // createValidations validates the creation of the resource func (alias *Alias) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){alias.validateResourceReferences} + return []func() (admission.Warnings, error){alias.validateResourceReferences, alias.validateSecretDestinations, alias.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -222,7 +245,22 @@ func (alias *Alias) updateValidations() []func(old runtime.Object) (admission.Wa func(old runtime.Object) (admission.Warnings, error) { return alias.validateResourceReferences() }, - alias.validateWriteOnceProperties} + alias.validateWriteOnceProperties, + func(old runtime.Object) (admission.Warnings, error) { + return alias.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return alias.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (alias *Alias) validateConfigMapDestinations() (admission.Warnings, error) { + if alias.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(alias, nil, alias.Spec.OperatorSpec.ConfigMapExpressions) } // validateResourceReferences validates all resource references @@ -234,6 +272,14 @@ func (alias *Alias) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (alias *Alias) validateSecretDestinations() (admission.Warnings, error) { + if alias.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(alias, nil, alias.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (alias *Alias) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Alias) @@ -320,6 +366,10 @@ type Alias_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AliasOperatorSpec `json:"operatorSpec,omitempty"` + // Properties: Put alias request properties. Properties *PutAliasRequestProperties `json:"properties,omitempty"` } @@ -363,6 +413,8 @@ func (alias *Alias_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReferenc // Set property "AzureName": alias.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Properties": if typedInput.Properties != nil { var properties1 PutAliasRequestProperties @@ -434,6 +486,18 @@ func (alias *Alias_Spec) AssignProperties_From_Alias_Spec(source *storage.Alias_ // AzureName alias.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AliasOperatorSpec + err := operatorSpec.AssignProperties_From_AliasOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AliasOperatorSpec() to populate field OperatorSpec") + } + alias.OperatorSpec = &operatorSpec + } else { + alias.OperatorSpec = nil + } + // Properties if source.Properties != nil { var property PutAliasRequestProperties @@ -458,6 +522,18 @@ func (alias *Alias_Spec) AssignProperties_To_Alias_Spec(destination *storage.Ali // AzureName destination.AzureName = alias.AzureName + // OperatorSpec + if alias.OperatorSpec != nil { + var operatorSpec storage.AliasOperatorSpec + err := alias.OperatorSpec.AssignProperties_To_AliasOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AliasOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = alias.OriginalVersion() @@ -741,6 +817,110 @@ type APIVersion string const APIVersion_Value = APIVersion("2021-10-01") +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AliasOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AliasOperatorSpec populates our AliasOperatorSpec from the provided source AliasOperatorSpec +func (operator *AliasOperatorSpec) AssignProperties_From_AliasOperatorSpec(source *storage.AliasOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AliasOperatorSpec populates the provided destination AliasOperatorSpec from our AliasOperatorSpec +func (operator *AliasOperatorSpec) AssignProperties_To_AliasOperatorSpec(destination *storage.AliasOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Put subscription properties. type PutAliasRequestProperties struct { // AdditionalProperties: Put alias request additional properties. diff --git a/v2/api/subscription/v1api20211001/alias_types_gen_test.go b/v2/api/subscription/v1api20211001/alias_types_gen_test.go index 1a9fe49fef7..c554faf248a 100644 --- a/v2/api/subscription/v1api20211001/alias_types_gen_test.go +++ b/v2/api/subscription/v1api20211001/alias_types_gen_test.go @@ -164,6 +164,102 @@ func AddRelatedPropertyGeneratorsForAlias(gens map[string]gopter.Gen) { gens["Status"] = Alias_STATUSGenerator() } +func Test_AliasOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from AliasOperatorSpec to AliasOperatorSpec via AssignProperties_To_AliasOperatorSpec & AssignProperties_From_AliasOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForAliasOperatorSpec, AliasOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForAliasOperatorSpec tests if a specific instance of AliasOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForAliasOperatorSpec(subject AliasOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.AliasOperatorSpec + err := copied.AssignProperties_To_AliasOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual AliasOperatorSpec + err = actual.AssignProperties_From_AliasOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_AliasOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AliasOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAliasOperatorSpec, AliasOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAliasOperatorSpec runs a test to see if a specific instance of AliasOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAliasOperatorSpec(subject AliasOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AliasOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AliasOperatorSpec instances for property testing - lazily instantiated by AliasOperatorSpecGenerator() +var aliasOperatorSpecGenerator gopter.Gen + +// AliasOperatorSpecGenerator returns a generator of AliasOperatorSpec instances for property testing. +func AliasOperatorSpecGenerator() gopter.Gen { + if aliasOperatorSpecGenerator != nil { + return aliasOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + aliasOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AliasOperatorSpec{}), generators) + + return aliasOperatorSpecGenerator +} + func Test_Alias_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -396,6 +492,7 @@ func AddIndependentPropertyGeneratorsForAlias_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForAlias_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAlias_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AliasOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(PutAliasRequestPropertiesGenerator()) } diff --git a/v2/api/subscription/v1api20211001/storage/alias_types_gen.go b/v2/api/subscription/v1api20211001/storage/alias_types_gen.go index bc23da783b2..a5e89524c2f 100644 --- a/v2/api/subscription/v1api20211001/storage/alias_types_gen.go +++ b/v2/api/subscription/v1api20211001/storage/alias_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (alias *Alias) SetConditions(conditions conditions.Conditions) { alias.Status.Conditions = conditions } +var _ configmaps.Exporter = &Alias{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (alias *Alias) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if alias.Spec.OperatorSpec == nil { + return nil + } + return alias.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Alias{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (alias *Alias) SecretDestinationExpressions() []*core.DestinationExpression { + if alias.Spec.OperatorSpec == nil { + return nil + } + return alias.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Alias{} // AzureName returns the Azure name of the resource @@ -142,6 +165,7 @@ type Alias_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. AzureName string `json:"azureName,omitempty"` + OperatorSpec *AliasOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` Properties *PutAliasRequestProperties `json:"properties,omitempty"` PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` @@ -204,6 +228,14 @@ type APIVersion string const APIVersion_Value = APIVersion("2021-10-01") +// Storage version of v1api20211001.AliasOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AliasOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20211001.PutAliasRequestProperties // Put subscription properties. type PutAliasRequestProperties struct { diff --git a/v2/api/subscription/v1api20211001/storage/alias_types_gen_test.go b/v2/api/subscription/v1api20211001/storage/alias_types_gen_test.go index bf4544caa9b..519923c854c 100644 --- a/v2/api/subscription/v1api20211001/storage/alias_types_gen_test.go +++ b/v2/api/subscription/v1api20211001/storage/alias_types_gen_test.go @@ -78,6 +78,60 @@ func AddRelatedPropertyGeneratorsForAlias(gens map[string]gopter.Gen) { gens["Status"] = Alias_STATUSGenerator() } +func Test_AliasOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of AliasOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForAliasOperatorSpec, AliasOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForAliasOperatorSpec runs a test to see if a specific instance of AliasOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForAliasOperatorSpec(subject AliasOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual AliasOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of AliasOperatorSpec instances for property testing - lazily instantiated by AliasOperatorSpecGenerator() +var aliasOperatorSpecGenerator gopter.Gen + +// AliasOperatorSpecGenerator returns a generator of AliasOperatorSpec instances for property testing. +func AliasOperatorSpecGenerator() gopter.Gen { + if aliasOperatorSpecGenerator != nil { + return aliasOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + aliasOperatorSpecGenerator = gen.Struct(reflect.TypeOf(AliasOperatorSpec{}), generators) + + return aliasOperatorSpecGenerator +} + func Test_Alias_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -227,6 +281,7 @@ func AddIndependentPropertyGeneratorsForAlias_Spec(gens map[string]gopter.Gen) { // AddRelatedPropertyGeneratorsForAlias_Spec is a factory method for creating gopter generators func AddRelatedPropertyGeneratorsForAlias_Spec(gens map[string]gopter.Gen) { + gens["OperatorSpec"] = gen.PtrOf(AliasOperatorSpecGenerator()) gens["Properties"] = gen.PtrOf(PutAliasRequestPropertiesGenerator()) } diff --git a/v2/api/subscription/v1api20211001/storage/structure.txt b/v2/api/subscription/v1api20211001/storage/structure.txt index 3ef141a207f..ab7beb8c34d 100644 --- a/v2/api/subscription/v1api20211001/storage/structure.txt +++ b/v2/api/subscription/v1api20211001/storage/structure.txt @@ -4,8 +4,12 @@ github.com/Azure/azure-service-operator/v2/api/subscription/v1api20211001/storag APIVersion: Enum (1 value) └── "2021-10-01" Alias: Resource -├── Spec: Object (4 properties) +├── Spec: Object (5 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Properties: *Object (7 properties) │ │ ├── AdditionalProperties: *Object (5 properties) diff --git a/v2/api/subscription/v1api20211001/storage/zz_generated.deepcopy.go b/v2/api/subscription/v1api20211001/storage/zz_generated.deepcopy.go index 071cc2884e5..48d36173fb6 100644 --- a/v2/api/subscription/v1api20211001/storage/zz_generated.deepcopy.go +++ b/v2/api/subscription/v1api20211001/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -74,6 +75,50 @@ func (in *AliasList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AliasOperatorSpec) DeepCopyInto(out *AliasOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AliasOperatorSpec. +func (in *AliasOperatorSpec) DeepCopy() *AliasOperatorSpec { + if in == nil { + return nil + } + out := new(AliasOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Alias_STATUS) DeepCopyInto(out *Alias_STATUS) { *out = *in @@ -131,6 +176,11 @@ func (in *Alias_STATUS) DeepCopy() *Alias_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Alias_Spec) DeepCopyInto(out *Alias_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AliasOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Properties != nil { in, out := &in.Properties, &out.Properties *out = new(PutAliasRequestProperties) diff --git a/v2/api/subscription/v1api20211001/structure.txt b/v2/api/subscription/v1api20211001/structure.txt index df77f935ce3..6c3f05a8c4e 100644 --- a/v2/api/subscription/v1api20211001/structure.txt +++ b/v2/api/subscription/v1api20211001/structure.txt @@ -4,8 +4,11 @@ github.com/Azure/azure-service-operator/v2/api/subscription/v1api20211001 APIVersion: Enum (1 value) └── "2021-10-01" Alias: Resource -├── Spec: Object (2 properties) +├── Spec: Object (3 properties) │ ├── AzureName: string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ └── Properties: *Object (6 properties) │ ├── AdditionalProperties: *Object (4 properties) │ │ ├── ManagementGroupId: *string diff --git a/v2/api/subscription/v1api20211001/zz_generated.deepcopy.go b/v2/api/subscription/v1api20211001/zz_generated.deepcopy.go index 8d29071bbf6..22bb2ccd888 100644 --- a/v2/api/subscription/v1api20211001/zz_generated.deepcopy.go +++ b/v2/api/subscription/v1api20211001/zz_generated.deepcopy.go @@ -11,6 +11,7 @@ package v1api20211001 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -73,6 +74,43 @@ func (in *AliasList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AliasOperatorSpec) DeepCopyInto(out *AliasOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AliasOperatorSpec. +func (in *AliasOperatorSpec) DeepCopy() *AliasOperatorSpec { + if in == nil { + return nil + } + out := new(AliasOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Alias_STATUS) DeepCopyInto(out *Alias_STATUS) { *out = *in @@ -123,6 +161,11 @@ func (in *Alias_STATUS) DeepCopy() *Alias_STATUS { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Alias_Spec) DeepCopyInto(out *Alias_Spec) { *out = *in + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(AliasOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Properties != nil { in, out := &in.Properties, &out.Properties *out = new(PutAliasRequestProperties) diff --git a/v2/api/synapse/v1api20210601/storage/structure.txt b/v2/api/synapse/v1api20210601/storage/structure.txt index ebce67989ac..43885edf030 100644 --- a/v2/api/synapse/v1api20210601/storage/structure.txt +++ b/v2/api/synapse/v1api20210601/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-06-01" Workspace: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (21 properties) +├── Spec: Object (22 properties) │ ├── AzureADOnlyAuthentication: *bool │ ├── AzureName: string │ ├── CspWorkspaceAdminProperties: *Object (2 properties) @@ -44,6 +44,10 @@ Workspace: Resource │ │ ├── LinkedAccessCheckOnTargetResource: *bool │ │ ├── PreventDataExfiltration: *bool │ │ └── PropertyBag: genruntime.PropertyBag +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag @@ -148,7 +152,7 @@ Workspace: Resource └── WorkspaceUID: *string WorkspacesBigDataPool: Resource ├── Owner: synapse/v1api20210601.Workspace -├── Spec: Object (23 properties) +├── Spec: Object (24 properties) │ ├── AutoPause: *Object (3 properties) │ │ ├── DelayInMinutes: *int │ │ ├── Enabled: *bool @@ -182,6 +186,10 @@ WorkspacesBigDataPool: Resource │ ├── NodeCount: *int │ ├── NodeSize: *string │ ├── NodeSizeFamily: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/synapse/v1api20210601/storage/workspace_types_gen.go b/v2/api/synapse/v1api20210601/storage/workspace_types_gen.go index 3fc7ab5b44f..11909b0e37d 100644 --- a/v2/api/synapse/v1api20210601/storage/workspace_types_gen.go +++ b/v2/api/synapse/v1api20210601/storage/workspace_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,6 +48,26 @@ func (workspace *Workspace) SetConditions(conditions conditions.Conditions) { workspace.Status.Conditions = conditions } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Workspace{} // AzureName returns the Azure name of the resource @@ -160,6 +183,7 @@ type Workspace_Spec struct { ManagedResourceGroupName *string `json:"managedResourceGroupName,omitempty"` ManagedVirtualNetwork *string `json:"managedVirtualNetwork,omitempty"` ManagedVirtualNetworkSettings *ManagedVirtualNetworkSettings `json:"managedVirtualNetworkSettings,omitempty"` + OperatorSpec *WorkspaceOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -376,6 +400,14 @@ type VirtualNetworkProfile_STATUS struct { PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` } +// Storage version of v1api20210601.WorkspaceOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspaceOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20210601.WorkspaceRepositoryConfiguration // Git integration settings type WorkspaceRepositoryConfiguration struct { diff --git a/v2/api/synapse/v1api20210601/storage/workspace_types_gen_test.go b/v2/api/synapse/v1api20210601/storage/workspace_types_gen_test.go index 31734a186a2..3c29df772ee 100644 --- a/v2/api/synapse/v1api20210601/storage/workspace_types_gen_test.go +++ b/v2/api/synapse/v1api20210601/storage/workspace_types_gen_test.go @@ -1535,6 +1535,61 @@ func AddIndependentPropertyGeneratorsForWorkspaceKeyDetails_STATUS(gens map[stri gens["Name"] = gen.PtrOf(gen.AlphaString()) } +func Test_WorkspaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspaceOperatorSpec runs a test to see if a specific instance of WorkspaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspaceOperatorSpec instances for property testing - lazily instantiated by +// WorkspaceOperatorSpecGenerator() +var workspaceOperatorSpecGenerator gopter.Gen + +// WorkspaceOperatorSpecGenerator returns a generator of WorkspaceOperatorSpec instances for property testing. +func WorkspaceOperatorSpecGenerator() gopter.Gen { + if workspaceOperatorSpecGenerator != nil { + return workspaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspaceOperatorSpec{}), generators) + + return workspaceOperatorSpecGenerator +} + func Test_WorkspaceRepositoryConfiguration_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1860,6 +1915,7 @@ func AddRelatedPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionDetailsGenerator()) gens["Identity"] = gen.PtrOf(ManagedIdentityGenerator()) gens["ManagedVirtualNetworkSettings"] = gen.PtrOf(ManagedVirtualNetworkSettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspaceOperatorSpecGenerator()) gens["PurviewConfiguration"] = gen.PtrOf(PurviewConfigurationGenerator()) gens["VirtualNetworkProfile"] = gen.PtrOf(VirtualNetworkProfileGenerator()) gens["WorkspaceRepositoryConfiguration"] = gen.PtrOf(WorkspaceRepositoryConfigurationGenerator()) diff --git a/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen.go b/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen.go index 86d3db59642..11c09124411 100644 --- a/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen.go +++ b/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (pool *WorkspacesBigDataPool) SetConditions(conditions conditions.Condition pool.Status.Conditions = conditions } +var _ configmaps.Exporter = &WorkspacesBigDataPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *WorkspacesBigDataPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesBigDataPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *WorkspacesBigDataPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &WorkspacesBigDataPool{} // AzureName returns the Azure name of the resource @@ -145,19 +168,20 @@ type WorkspacesBigDataPool_Spec struct { // AzureName: The name of the resource in Azure. This is often the same as the name of the resource in Kubernetes but it // doesn't have to be. - AzureName string `json:"azureName,omitempty"` - CacheSize *int `json:"cacheSize,omitempty"` - CustomLibraries []LibraryInfo `json:"customLibraries,omitempty"` - DefaultSparkLogFolder *string `json:"defaultSparkLogFolder,omitempty"` - DynamicExecutorAllocation *DynamicExecutorAllocation `json:"dynamicExecutorAllocation,omitempty"` - IsAutotuneEnabled *bool `json:"isAutotuneEnabled,omitempty"` - IsComputeIsolationEnabled *bool `json:"isComputeIsolationEnabled,omitempty"` - LibraryRequirements *LibraryRequirements `json:"libraryRequirements,omitempty"` - Location *string `json:"location,omitempty"` - NodeCount *int `json:"nodeCount,omitempty"` - NodeSize *string `json:"nodeSize,omitempty"` - NodeSizeFamily *string `json:"nodeSizeFamily,omitempty"` - OriginalVersion string `json:"originalVersion,omitempty"` + AzureName string `json:"azureName,omitempty"` + CacheSize *int `json:"cacheSize,omitempty"` + CustomLibraries []LibraryInfo `json:"customLibraries,omitempty"` + DefaultSparkLogFolder *string `json:"defaultSparkLogFolder,omitempty"` + DynamicExecutorAllocation *DynamicExecutorAllocation `json:"dynamicExecutorAllocation,omitempty"` + IsAutotuneEnabled *bool `json:"isAutotuneEnabled,omitempty"` + IsComputeIsolationEnabled *bool `json:"isComputeIsolationEnabled,omitempty"` + LibraryRequirements *LibraryRequirements `json:"libraryRequirements,omitempty"` + Location *string `json:"location,omitempty"` + NodeCount *int `json:"nodeCount,omitempty"` + NodeSize *string `json:"nodeSize,omitempty"` + NodeSizeFamily *string `json:"nodeSizeFamily,omitempty"` + OperatorSpec *WorkspacesBigDataPoolOperatorSpec `json:"operatorSpec,omitempty"` + OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -354,6 +378,14 @@ type SparkConfigProperties_STATUS struct { Time *string `json:"time,omitempty"` } +// Storage version of v1api20210601.WorkspacesBigDataPoolOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesBigDataPoolOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + func init() { SchemeBuilder.Register(&WorkspacesBigDataPool{}, &WorkspacesBigDataPoolList{}) } diff --git a/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen_test.go b/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen_test.go index 2da83e05fe7..ce6dae33e49 100644 --- a/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen_test.go +++ b/v2/api/synapse/v1api20210601/storage/workspaces_big_data_pool_types_gen_test.go @@ -836,6 +836,61 @@ func AddRelatedPropertyGeneratorsForWorkspacesBigDataPool(gens map[string]gopter gens["Status"] = WorkspacesBigDataPool_STATUSGenerator() } +func Test_WorkspacesBigDataPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesBigDataPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec, WorkspacesBigDataPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec runs a test to see if a specific instance of WorkspacesBigDataPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec(subject WorkspacesBigDataPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesBigDataPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesBigDataPoolOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesBigDataPoolOperatorSpecGenerator() +var workspacesBigDataPoolOperatorSpecGenerator gopter.Gen + +// WorkspacesBigDataPoolOperatorSpecGenerator returns a generator of WorkspacesBigDataPoolOperatorSpec instances for property testing. +func WorkspacesBigDataPoolOperatorSpecGenerator() gopter.Gen { + if workspacesBigDataPoolOperatorSpecGenerator != nil { + return workspacesBigDataPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesBigDataPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesBigDataPoolOperatorSpec{}), generators) + + return workspacesBigDataPoolOperatorSpecGenerator +} + func Test_WorkspacesBigDataPool_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1028,5 +1083,6 @@ func AddRelatedPropertyGeneratorsForWorkspacesBigDataPool_Spec(gens map[string]g gens["CustomLibraries"] = gen.SliceOf(LibraryInfoGenerator()) gens["DynamicExecutorAllocation"] = gen.PtrOf(DynamicExecutorAllocationGenerator()) gens["LibraryRequirements"] = gen.PtrOf(LibraryRequirementsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesBigDataPoolOperatorSpecGenerator()) gens["SparkConfigProperties"] = gen.PtrOf(SparkConfigPropertiesGenerator()) } diff --git a/v2/api/synapse/v1api20210601/storage/zz_generated.deepcopy.go b/v2/api/synapse/v1api20210601/storage/zz_generated.deepcopy.go index 5b13cc27dae..5c1f063a4a3 100644 --- a/v2/api/synapse/v1api20210601/storage/zz_generated.deepcopy.go +++ b/v2/api/synapse/v1api20210601/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1275,6 +1276,50 @@ func (in *WorkspaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceOperatorSpec. +func (in *WorkspaceOperatorSpec) DeepCopy() *WorkspaceOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceRepositoryConfiguration) DeepCopyInto(out *WorkspaceRepositoryConfiguration) { *out = *in @@ -1626,6 +1671,11 @@ func (in *Workspace_Spec) DeepCopyInto(out *Workspace_Spec) { *out = new(ManagedVirtualNetworkSettings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1751,6 +1801,50 @@ func (in *WorkspacesBigDataPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesBigDataPoolOperatorSpec) DeepCopyInto(out *WorkspacesBigDataPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesBigDataPoolOperatorSpec. +func (in *WorkspacesBigDataPoolOperatorSpec) DeepCopy() *WorkspacesBigDataPoolOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesBigDataPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesBigDataPool_STATUS) DeepCopyInto(out *WorkspacesBigDataPool_STATUS) { *out = *in @@ -1974,6 +2068,11 @@ func (in *WorkspacesBigDataPool_Spec) DeepCopyInto(out *WorkspacesBigDataPool_Sp *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesBigDataPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/synapse/v1api20210601/structure.txt b/v2/api/synapse/v1api20210601/structure.txt index 39ce1f0c1b1..08d0ba3339b 100644 --- a/v2/api/synapse/v1api20210601/structure.txt +++ b/v2/api/synapse/v1api20210601/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2021-06-01" Workspace: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (19 properties) +├── Spec: Object (20 properties) │ ├── AzureADOnlyAuthentication: *bool │ ├── AzureName: string │ ├── CspWorkspaceAdminProperties: *Object (1 property) @@ -38,6 +38,9 @@ Workspace: Resource │ │ ├── AllowedAadTenantIdsForLinking: string[] │ │ ├── LinkedAccessCheckOnTargetResource: *bool │ │ └── PreventDataExfiltration: *bool +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *Enum (2 values) │ │ ├── "Disabled" @@ -131,7 +134,7 @@ Workspace: Resource └── WorkspaceUID: *string WorkspacesBigDataPool: Resource ├── Owner: Workspace -├── Spec: Object (21 properties) +├── Spec: Object (22 properties) │ ├── AutoPause: *Object (2 properties) │ │ ├── DelayInMinutes: *int │ │ └── Enabled: *bool @@ -171,6 +174,9 @@ WorkspacesBigDataPool: Resource │ │ ├── "HardwareAcceleratedGPU" │ │ ├── "MemoryOptimized" │ │ └── "None" +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── ProvisioningState: *string │ ├── SessionLevelPackagesEnabled: *bool diff --git a/v2/api/synapse/v1api20210601/workspace_types_gen.go b/v2/api/synapse/v1api20210601/workspace_types_gen.go index 21744b106b6..c81f5ef1aa6 100644 --- a/v2/api/synapse/v1api20210601/workspace_types_gen.go +++ b/v2/api/synapse/v1api20210601/workspace_types_gen.go @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -93,6 +95,26 @@ func (workspace *Workspace) defaultAzureName() { // defaultImpl applies the code generated defaults to the Workspace resource func (workspace *Workspace) defaultImpl() { workspace.defaultAzureName() } +var _ configmaps.Exporter = &Workspace{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (workspace *Workspace) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Workspace{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (workspace *Workspace) SecretDestinationExpressions() []*core.DestinationExpression { + if workspace.Spec.OperatorSpec == nil { + return nil + } + return workspace.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Workspace{} // InitializeSpec initializes the spec for this resource from the given status @@ -211,7 +233,7 @@ func (workspace *Workspace) ValidateUpdate(old runtime.Object) (admission.Warnin // createValidations validates the creation of the resource func (workspace *Workspace) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateOptionalConfigMapReferences} + return []func() (admission.Warnings, error){workspace.validateResourceReferences, workspace.validateOwnerReference, workspace.validateSecretDestinations, workspace.validateConfigMapDestinations, workspace.validateOptionalConfigMapReferences} } // deleteValidations validates the deletion of the resource @@ -229,12 +251,26 @@ func (workspace *Workspace) updateValidations() []func(old runtime.Object) (admi func(old runtime.Object) (admission.Warnings, error) { return workspace.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return workspace.validateConfigMapDestinations() + }, func(old runtime.Object) (admission.Warnings, error) { return workspace.validateOptionalConfigMapReferences() }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (workspace *Workspace) validateConfigMapDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOptionalConfigMapReferences validates all optional configmap reference pairs to ensure that at most 1 is set func (workspace *Workspace) validateOptionalConfigMapReferences() (admission.Warnings, error) { refs, err := reflecthelpers.FindOptionalConfigMapReferences(&workspace.Spec) @@ -258,6 +294,14 @@ func (workspace *Workspace) validateResourceReferences() (admission.Warnings, er return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (workspace *Workspace) validateSecretDestinations() (admission.Warnings, error) { + if workspace.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(workspace, nil, workspace.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (workspace *Workspace) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Workspace) @@ -380,6 +424,10 @@ type Workspace_Spec struct { // ManagedVirtualNetworkSettings: Managed Virtual Network Settings ManagedVirtualNetworkSettings *ManagedVirtualNetworkSettings `json:"managedVirtualNetworkSettings,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspaceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -672,6 +720,8 @@ func (workspace *Workspace_Spec) PopulateFromARM(owner genruntime.ArbitraryOwner } } + // no assignment for property "OperatorSpec" + // Set property "Owner": workspace.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -896,6 +946,18 @@ func (workspace *Workspace_Spec) AssignProperties_From_Workspace_Spec(source *st workspace.ManagedVirtualNetworkSettings = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspaceOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspaceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspaceOperatorSpec() to populate field OperatorSpec") + } + workspace.OperatorSpec = &operatorSpec + } else { + workspace.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1060,6 +1122,18 @@ func (workspace *Workspace_Spec) AssignProperties_To_Workspace_Spec(destination destination.ManagedVirtualNetworkSettings = nil } + // OperatorSpec + if workspace.OperatorSpec != nil { + var operatorSpec storage.WorkspaceOperatorSpec + err := workspace.OperatorSpec.AssignProperties_To_WorkspaceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspaceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = workspace.OriginalVersion() @@ -3806,6 +3880,110 @@ func (profile *VirtualNetworkProfile_STATUS) AssignProperties_To_VirtualNetworkP return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspaceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspaceOperatorSpec populates our WorkspaceOperatorSpec from the provided source WorkspaceOperatorSpec +func (operator *WorkspaceOperatorSpec) AssignProperties_From_WorkspaceOperatorSpec(source *storage.WorkspaceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspaceOperatorSpec populates the provided destination WorkspaceOperatorSpec from our WorkspaceOperatorSpec +func (operator *WorkspaceOperatorSpec) AssignProperties_To_WorkspaceOperatorSpec(destination *storage.WorkspaceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Disabled","Enabled"} type WorkspaceProperties_PublicNetworkAccess string diff --git a/v2/api/synapse/v1api20210601/workspace_types_gen_test.go b/v2/api/synapse/v1api20210601/workspace_types_gen_test.go index 9567b86e25b..f2eee462e13 100644 --- a/v2/api/synapse/v1api20210601/workspace_types_gen_test.go +++ b/v2/api/synapse/v1api20210601/workspace_types_gen_test.go @@ -2587,6 +2587,103 @@ func AddIndependentPropertyGeneratorsForWorkspaceKeyDetails_STATUS(gens map[stri gens["Name"] = gen.PtrOf(gen.AlphaString()) } +func Test_WorkspaceOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspaceOperatorSpec to WorkspaceOperatorSpec via AssignProperties_To_WorkspaceOperatorSpec & AssignProperties_From_WorkspaceOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspaceOperatorSpec tests if a specific instance of WorkspaceOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspaceOperatorSpec + err := copied.AssignProperties_To_WorkspaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspaceOperatorSpec + err = actual.AssignProperties_From_WorkspaceOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspaceOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspaceOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspaceOperatorSpec, WorkspaceOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspaceOperatorSpec runs a test to see if a specific instance of WorkspaceOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspaceOperatorSpec(subject WorkspaceOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspaceOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspaceOperatorSpec instances for property testing - lazily instantiated by +// WorkspaceOperatorSpecGenerator() +var workspaceOperatorSpecGenerator gopter.Gen + +// WorkspaceOperatorSpecGenerator returns a generator of WorkspaceOperatorSpec instances for property testing. +func WorkspaceOperatorSpecGenerator() gopter.Gen { + if workspaceOperatorSpecGenerator != nil { + return workspaceOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspaceOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspaceOperatorSpec{}), generators) + + return workspaceOperatorSpecGenerator +} + func Test_WorkspaceRepositoryConfiguration_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3079,6 +3176,7 @@ func AddRelatedPropertyGeneratorsForWorkspace_Spec(gens map[string]gopter.Gen) { gens["Encryption"] = gen.PtrOf(EncryptionDetailsGenerator()) gens["Identity"] = gen.PtrOf(ManagedIdentityGenerator()) gens["ManagedVirtualNetworkSettings"] = gen.PtrOf(ManagedVirtualNetworkSettingsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspaceOperatorSpecGenerator()) gens["PurviewConfiguration"] = gen.PtrOf(PurviewConfigurationGenerator()) gens["VirtualNetworkProfile"] = gen.PtrOf(VirtualNetworkProfileGenerator()) gens["WorkspaceRepositoryConfiguration"] = gen.PtrOf(WorkspaceRepositoryConfigurationGenerator()) diff --git a/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen.go b/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen.go index e66718ec909..fd02c9a8bd6 100644 --- a/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen.go +++ b/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (pool *WorkspacesBigDataPool) defaultAzureName() { // defaultImpl applies the code generated defaults to the WorkspacesBigDataPool resource func (pool *WorkspacesBigDataPool) defaultImpl() { pool.defaultAzureName() } +var _ configmaps.Exporter = &WorkspacesBigDataPool{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (pool *WorkspacesBigDataPool) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &WorkspacesBigDataPool{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (pool *WorkspacesBigDataPool) SecretDestinationExpressions() []*core.DestinationExpression { + if pool.Spec.OperatorSpec == nil { + return nil + } + return pool.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &WorkspacesBigDataPool{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (pool *WorkspacesBigDataPool) ValidateUpdate(old runtime.Object) (admission // createValidations validates the creation of the resource func (pool *WorkspacesBigDataPool) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference} + return []func() (admission.Warnings, error){pool.validateResourceReferences, pool.validateOwnerReference, pool.validateSecretDestinations, pool.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (pool *WorkspacesBigDataPool) updateValidations() []func(old runtime.Object func(old runtime.Object) (admission.Warnings, error) { return pool.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return pool.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (pool *WorkspacesBigDataPool) validateConfigMapDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (pool *WorkspacesBigDataPool) validateResourceReferences() (admission.Warni return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (pool *WorkspacesBigDataPool) validateSecretDestinations() (admission.Warnings, error) { + if pool.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(pool, nil, pool.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (pool *WorkspacesBigDataPool) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*WorkspacesBigDataPool) @@ -370,6 +415,10 @@ type WorkspacesBigDataPool_Spec struct { // NodeSizeFamily: The kind of nodes that the Big Data pool provides. NodeSizeFamily *BigDataPoolResourceProperties_NodeSizeFamily `json:"nodeSizeFamily,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *WorkspacesBigDataPoolOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -696,6 +745,8 @@ func (pool *WorkspacesBigDataPool_Spec) PopulateFromARM(owner genruntime.Arbitra } } + // no assignment for property "OperatorSpec" + // Set property "Owner": pool.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -932,6 +983,18 @@ func (pool *WorkspacesBigDataPool_Spec) AssignProperties_From_WorkspacesBigDataP pool.NodeSizeFamily = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec WorkspacesBigDataPoolOperatorSpec + err := operatorSpec.AssignProperties_From_WorkspacesBigDataPoolOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_WorkspacesBigDataPoolOperatorSpec() to populate field OperatorSpec") + } + pool.OperatorSpec = &operatorSpec + } else { + pool.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1094,6 +1157,18 @@ func (pool *WorkspacesBigDataPool_Spec) AssignProperties_To_WorkspacesBigDataPoo destination.NodeSizeFamily = nil } + // OperatorSpec + if pool.OperatorSpec != nil { + var operatorSpec storage.WorkspacesBigDataPoolOperatorSpec + err := pool.OperatorSpec.AssignProperties_To_WorkspacesBigDataPoolOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_WorkspacesBigDataPoolOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = pool.OriginalVersion() @@ -3586,6 +3661,110 @@ func (properties *SparkConfigProperties_STATUS) AssignProperties_To_SparkConfigP return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type WorkspacesBigDataPoolOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_WorkspacesBigDataPoolOperatorSpec populates our WorkspacesBigDataPoolOperatorSpec from the provided source WorkspacesBigDataPoolOperatorSpec +func (operator *WorkspacesBigDataPoolOperatorSpec) AssignProperties_From_WorkspacesBigDataPoolOperatorSpec(source *storage.WorkspacesBigDataPoolOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_WorkspacesBigDataPoolOperatorSpec populates the provided destination WorkspacesBigDataPoolOperatorSpec from our WorkspacesBigDataPoolOperatorSpec +func (operator *WorkspacesBigDataPoolOperatorSpec) AssignProperties_To_WorkspacesBigDataPoolOperatorSpec(destination *storage.WorkspacesBigDataPoolOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"Artifact","File"} type SparkConfigProperties_ConfigurationType string diff --git a/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen_test.go b/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen_test.go index 7f7bb8ac4dc..f76c91809b0 100644 --- a/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen_test.go +++ b/v2/api/synapse/v1api20210601/workspaces_big_data_pool_types_gen_test.go @@ -1426,6 +1426,103 @@ func AddRelatedPropertyGeneratorsForWorkspacesBigDataPool(gens map[string]gopter gens["Status"] = WorkspacesBigDataPool_STATUSGenerator() } +func Test_WorkspacesBigDataPoolOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from WorkspacesBigDataPoolOperatorSpec to WorkspacesBigDataPoolOperatorSpec via AssignProperties_To_WorkspacesBigDataPoolOperatorSpec & AssignProperties_From_WorkspacesBigDataPoolOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForWorkspacesBigDataPoolOperatorSpec, WorkspacesBigDataPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForWorkspacesBigDataPoolOperatorSpec tests if a specific instance of WorkspacesBigDataPoolOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForWorkspacesBigDataPoolOperatorSpec(subject WorkspacesBigDataPoolOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.WorkspacesBigDataPoolOperatorSpec + err := copied.AssignProperties_To_WorkspacesBigDataPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual WorkspacesBigDataPoolOperatorSpec + err = actual.AssignProperties_From_WorkspacesBigDataPoolOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_WorkspacesBigDataPoolOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of WorkspacesBigDataPoolOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec, WorkspacesBigDataPoolOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec runs a test to see if a specific instance of WorkspacesBigDataPoolOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForWorkspacesBigDataPoolOperatorSpec(subject WorkspacesBigDataPoolOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual WorkspacesBigDataPoolOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of WorkspacesBigDataPoolOperatorSpec instances for property testing - lazily instantiated by +// WorkspacesBigDataPoolOperatorSpecGenerator() +var workspacesBigDataPoolOperatorSpecGenerator gopter.Gen + +// WorkspacesBigDataPoolOperatorSpecGenerator returns a generator of WorkspacesBigDataPoolOperatorSpec instances for property testing. +func WorkspacesBigDataPoolOperatorSpecGenerator() gopter.Gen { + if workspacesBigDataPoolOperatorSpecGenerator != nil { + return workspacesBigDataPoolOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + workspacesBigDataPoolOperatorSpecGenerator = gen.Struct(reflect.TypeOf(WorkspacesBigDataPoolOperatorSpec{}), generators) + + return workspacesBigDataPoolOperatorSpecGenerator +} + func Test_WorkspacesBigDataPool_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1723,5 +1820,6 @@ func AddRelatedPropertyGeneratorsForWorkspacesBigDataPool_Spec(gens map[string]g gens["CustomLibraries"] = gen.SliceOf(LibraryInfoGenerator()) gens["DynamicExecutorAllocation"] = gen.PtrOf(DynamicExecutorAllocationGenerator()) gens["LibraryRequirements"] = gen.PtrOf(LibraryRequirementsGenerator()) + gens["OperatorSpec"] = gen.PtrOf(WorkspacesBigDataPoolOperatorSpecGenerator()) gens["SparkConfigProperties"] = gen.PtrOf(SparkConfigPropertiesGenerator()) } diff --git a/v2/api/synapse/v1api20210601/zz_generated.deepcopy.go b/v2/api/synapse/v1api20210601/zz_generated.deepcopy.go index 0bb20730a36..ba5a648a12b 100644 --- a/v2/api/synapse/v1api20210601/zz_generated.deepcopy.go +++ b/v2/api/synapse/v1api20210601/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20210601 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -1028,6 +1029,43 @@ func (in *WorkspaceList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceOperatorSpec) DeepCopyInto(out *WorkspaceOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceOperatorSpec. +func (in *WorkspaceOperatorSpec) DeepCopy() *WorkspaceOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspaceOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceRepositoryConfiguration) DeepCopyInto(out *WorkspaceRepositoryConfiguration) { *out = *in @@ -1358,6 +1396,11 @@ func (in *Workspace_Spec) DeepCopyInto(out *Workspace_Spec) { *out = new(ManagedVirtualNetworkSettings) (*in).DeepCopyInto(*out) } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspaceOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -1476,6 +1519,43 @@ func (in *WorkspacesBigDataPoolList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspacesBigDataPoolOperatorSpec) DeepCopyInto(out *WorkspacesBigDataPoolOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspacesBigDataPoolOperatorSpec. +func (in *WorkspacesBigDataPoolOperatorSpec) DeepCopy() *WorkspacesBigDataPoolOperatorSpec { + if in == nil { + return nil + } + out := new(WorkspacesBigDataPoolOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspacesBigDataPool_STATUS) DeepCopyInto(out *WorkspacesBigDataPool_STATUS) { *out = *in @@ -1692,6 +1772,11 @@ func (in *WorkspacesBigDataPool_Spec) DeepCopyInto(out *WorkspacesBigDataPool_Sp *out = new(BigDataPoolResourceProperties_NodeSizeFamily) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(WorkspacesBigDataPoolOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/web/v1api20220301/server_farm_types_gen.go b/v2/api/web/v1api20220301/server_farm_types_gen.go index 72677a45353..e23a39fb181 100644 --- a/v2/api/web/v1api20220301/server_farm_types_gen.go +++ b/v2/api/web/v1api20220301/server_farm_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (farm *ServerFarm) defaultAzureName() { // defaultImpl applies the code generated defaults to the ServerFarm resource func (farm *ServerFarm) defaultImpl() { farm.defaultAzureName() } +var _ configmaps.Exporter = &ServerFarm{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (farm *ServerFarm) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if farm.Spec.OperatorSpec == nil { + return nil + } + return farm.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServerFarm{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (farm *ServerFarm) SecretDestinationExpressions() []*core.DestinationExpression { + if farm.Spec.OperatorSpec == nil { + return nil + } + return farm.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &ServerFarm{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (farm *ServerFarm) ValidateUpdate(old runtime.Object) (admission.Warnings, // createValidations validates the creation of the resource func (farm *ServerFarm) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){farm.validateResourceReferences, farm.validateOwnerReference} + return []func() (admission.Warnings, error){farm.validateResourceReferences, farm.validateOwnerReference, farm.validateSecretDestinations, farm.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (farm *ServerFarm) updateValidations() []func(old runtime.Object) (admissio func(old runtime.Object) (admission.Warnings, error) { return farm.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return farm.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return farm.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (farm *ServerFarm) validateConfigMapDestinations() (admission.Warnings, error) { + if farm.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(farm, nil, farm.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (farm *ServerFarm) validateResourceReferences() (admission.Warnings, error) return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (farm *ServerFarm) validateSecretDestinations() (admission.Warnings, error) { + if farm.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(farm, nil, farm.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (farm *ServerFarm) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*ServerFarm) @@ -370,6 +415,10 @@ type ServerFarm_Spec struct { // MaximumElasticWorkerCount: Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan MaximumElasticWorkerCount *int `json:"maximumElasticWorkerCount,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *ServerFarmOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -667,6 +716,8 @@ func (farm *ServerFarm_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerRefe } } + // no assignment for property "OperatorSpec" + // Set property "Owner": farm.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -895,6 +946,18 @@ func (farm *ServerFarm_Spec) AssignProperties_From_ServerFarm_Spec(source *stora // MaximumElasticWorkerCount farm.MaximumElasticWorkerCount = genruntime.ClonePointerToInt(source.MaximumElasticWorkerCount) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec ServerFarmOperatorSpec + err := operatorSpec.AssignProperties_From_ServerFarmOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_ServerFarmOperatorSpec() to populate field OperatorSpec") + } + farm.OperatorSpec = &operatorSpec + } else { + farm.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1046,6 +1109,18 @@ func (farm *ServerFarm_Spec) AssignProperties_To_ServerFarm_Spec(destination *st // MaximumElasticWorkerCount destination.MaximumElasticWorkerCount = genruntime.ClonePointerToInt(farm.MaximumElasticWorkerCount) + // OperatorSpec + if farm.OperatorSpec != nil { + var operatorSpec storage.ServerFarmOperatorSpec + err := farm.OperatorSpec.AssignProperties_To_ServerFarmOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_ServerFarmOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = farm.OriginalVersion() @@ -2664,6 +2739,110 @@ var serverfarm_Properties_Status_STATUS_Values = map[string]Serverfarm_Propertie "ready": Serverfarm_Properties_Status_STATUS_Ready, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServerFarmOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_ServerFarmOperatorSpec populates our ServerFarmOperatorSpec from the provided source ServerFarmOperatorSpec +func (operator *ServerFarmOperatorSpec) AssignProperties_From_ServerFarmOperatorSpec(source *storage.ServerFarmOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_ServerFarmOperatorSpec populates the provided destination ServerFarmOperatorSpec from our ServerFarmOperatorSpec +func (operator *ServerFarmOperatorSpec) AssignProperties_To_ServerFarmOperatorSpec(destination *storage.ServerFarmOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Description of a SKU for a scalable resource. type SkuDescription struct { // Capabilities: Capabilities of the SKU, e.g., is traffic manager enabled? diff --git a/v2/api/web/v1api20220301/server_farm_types_gen_test.go b/v2/api/web/v1api20220301/server_farm_types_gen_test.go index d36ee3da3bb..23ac19b05f1 100644 --- a/v2/api/web/v1api20220301/server_farm_types_gen_test.go +++ b/v2/api/web/v1api20220301/server_farm_types_gen_test.go @@ -982,6 +982,103 @@ func AddRelatedPropertyGeneratorsForServerFarm(gens map[string]gopter.Gen) { gens["Status"] = ServerFarm_STATUSGenerator() } +func Test_ServerFarmOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from ServerFarmOperatorSpec to ServerFarmOperatorSpec via AssignProperties_To_ServerFarmOperatorSpec & AssignProperties_From_ServerFarmOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForServerFarmOperatorSpec, ServerFarmOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForServerFarmOperatorSpec tests if a specific instance of ServerFarmOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForServerFarmOperatorSpec(subject ServerFarmOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.ServerFarmOperatorSpec + err := copied.AssignProperties_To_ServerFarmOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual ServerFarmOperatorSpec + err = actual.AssignProperties_From_ServerFarmOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_ServerFarmOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServerFarmOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServerFarmOperatorSpec, ServerFarmOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServerFarmOperatorSpec runs a test to see if a specific instance of ServerFarmOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServerFarmOperatorSpec(subject ServerFarmOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServerFarmOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServerFarmOperatorSpec instances for property testing - lazily instantiated by +// ServerFarmOperatorSpecGenerator() +var serverFarmOperatorSpecGenerator gopter.Gen + +// ServerFarmOperatorSpecGenerator returns a generator of ServerFarmOperatorSpec instances for property testing. +func ServerFarmOperatorSpecGenerator() gopter.Gen { + if serverFarmOperatorSpecGenerator != nil { + return serverFarmOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serverFarmOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServerFarmOperatorSpec{}), generators) + + return serverFarmOperatorSpecGenerator +} + func Test_ServerFarm_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -1268,6 +1365,7 @@ func AddRelatedPropertyGeneratorsForServerFarm_Spec(gens map[string]gopter.Gen) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostingEnvironmentProfile"] = gen.PtrOf(HostingEnvironmentProfileGenerator()) gens["KubeEnvironmentProfile"] = gen.PtrOf(KubeEnvironmentProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServerFarmOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuDescriptionGenerator()) } diff --git a/v2/api/web/v1api20220301/site_types_gen.go b/v2/api/web/v1api20220301/site_types_gen.go index c806c989cbb..e0c2a736f4e 100644 --- a/v2/api/web/v1api20220301/site_types_gen.go +++ b/v2/api/web/v1api20220301/site_types_gen.go @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -91,6 +94,26 @@ func (site *Site) defaultAzureName() { // defaultImpl applies the code generated defaults to the Site resource func (site *Site) defaultImpl() { site.defaultAzureName() } +var _ configmaps.Exporter = &Site{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (site *Site) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if site.Spec.OperatorSpec == nil { + return nil + } + return site.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Site{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (site *Site) SecretDestinationExpressions() []*core.DestinationExpression { + if site.Spec.OperatorSpec == nil { + return nil + } + return site.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.ImportableResource = &Site{} // InitializeSpec initializes the spec for this resource from the given status @@ -209,7 +232,7 @@ func (site *Site) ValidateUpdate(old runtime.Object) (admission.Warnings, error) // createValidations validates the creation of the resource func (site *Site) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){site.validateResourceReferences, site.validateOwnerReference} + return []func() (admission.Warnings, error){site.validateResourceReferences, site.validateOwnerReference, site.validateSecretDestinations, site.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -227,7 +250,21 @@ func (site *Site) updateValidations() []func(old runtime.Object) (admission.Warn func(old runtime.Object) (admission.Warnings, error) { return site.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return site.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return site.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (site *Site) validateConfigMapDestinations() (admission.Warnings, error) { + if site.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(site, nil, site.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -244,6 +281,14 @@ func (site *Site) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (site *Site) validateSecretDestinations() (admission.Warnings, error) { + if site.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(site, nil, site.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (site *Site) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*Site) @@ -400,6 +445,10 @@ type Site_Spec struct { // Location: Resource Location. Location *string `json:"location,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *SiteOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -879,6 +928,8 @@ func (site *Site_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, site.Location = &location } + // no assignment for property "OperatorSpec" + // Set property "Owner": site.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1197,6 +1248,18 @@ func (site *Site_Spec) AssignProperties_From_Site_Spec(source *storage.Site_Spec // Location site.Location = genruntime.ClonePointerToString(source.Location) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec SiteOperatorSpec + err := operatorSpec.AssignProperties_From_SiteOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_SiteOperatorSpec() to populate field OperatorSpec") + } + site.OperatorSpec = &operatorSpec + } else { + site.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1459,6 +1522,18 @@ func (site *Site_Spec) AssignProperties_To_Site_Spec(destination *storage.Site_S // Location destination.Location = genruntime.ClonePointerToString(site.Location) + // OperatorSpec + if site.OperatorSpec != nil { + var operatorSpec storage.SiteOperatorSpec + err := site.OperatorSpec.AssignProperties_To_SiteOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_SiteOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = site.OriginalVersion() @@ -9161,6 +9236,110 @@ func (config *SiteConfig_STATUS) AssignProperties_To_SiteConfig_STATUS(destinati return nil } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SiteOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_SiteOperatorSpec populates our SiteOperatorSpec from the provided source SiteOperatorSpec +func (operator *SiteOperatorSpec) AssignProperties_From_SiteOperatorSpec(source *storage.SiteOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_SiteOperatorSpec populates the provided destination SiteOperatorSpec from our SiteOperatorSpec +func (operator *SiteOperatorSpec) AssignProperties_To_SiteOperatorSpec(destination *storage.SiteOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // The status of the last successful slot swap operation. type SlotSwapStatus_STATUS struct { // DestinationSlotName: The destination slot of the last swap operation. diff --git a/v2/api/web/v1api20220301/site_types_gen_test.go b/v2/api/web/v1api20220301/site_types_gen_test.go index 99a176f33ec..b32466abf1e 100644 --- a/v2/api/web/v1api20220301/site_types_gen_test.go +++ b/v2/api/web/v1api20220301/site_types_gen_test.go @@ -4842,6 +4842,102 @@ func AddIndependentPropertyGeneratorsForSiteMachineKey_STATUS(gens map[string]go gens["ValidationKey"] = gen.PtrOf(gen.AlphaString()) } +func Test_SiteOperatorSpec_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MaxSize = 10 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip from SiteOperatorSpec to SiteOperatorSpec via AssignProperties_To_SiteOperatorSpec & AssignProperties_From_SiteOperatorSpec returns original", + prop.ForAll(RunPropertyAssignmentTestForSiteOperatorSpec, SiteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(false, 240, os.Stdout)) +} + +// RunPropertyAssignmentTestForSiteOperatorSpec tests if a specific instance of SiteOperatorSpec can be assigned to storage and back losslessly +func RunPropertyAssignmentTestForSiteOperatorSpec(subject SiteOperatorSpec) string { + // Copy subject to make sure assignment doesn't modify it + copied := subject.DeepCopy() + + // Use AssignPropertiesTo() for the first stage of conversion + var other storage.SiteOperatorSpec + err := copied.AssignProperties_To_SiteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Use AssignPropertiesFrom() to convert back to our original type + var actual SiteOperatorSpec + err = actual.AssignProperties_From_SiteOperatorSpec(&other) + if err != nil { + return err.Error() + } + + // Check for a match + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +func Test_SiteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SiteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSiteOperatorSpec, SiteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSiteOperatorSpec runs a test to see if a specific instance of SiteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSiteOperatorSpec(subject SiteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SiteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SiteOperatorSpec instances for property testing - lazily instantiated by SiteOperatorSpecGenerator() +var siteOperatorSpecGenerator gopter.Gen + +// SiteOperatorSpecGenerator returns a generator of SiteOperatorSpec instances for property testing. +func SiteOperatorSpecGenerator() gopter.Gen { + if siteOperatorSpecGenerator != nil { + return siteOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + siteOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SiteOperatorSpec{}), generators) + + return siteOperatorSpecGenerator +} + func Test_Site_STATUS_WhenPropertiesConverted_RoundTripsWithoutLoss(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -5099,6 +5195,7 @@ func AddRelatedPropertyGeneratorsForSite_Spec(gens map[string]gopter.Gen) { gens["HostNameSslStates"] = gen.SliceOf(HostNameSslStateGenerator()) gens["HostingEnvironmentProfile"] = gen.PtrOf(HostingEnvironmentProfileGenerator()) gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SiteOperatorSpecGenerator()) gens["SiteConfig"] = gen.PtrOf(SiteConfigGenerator()) } diff --git a/v2/api/web/v1api20220301/storage/server_farm_types_gen.go b/v2/api/web/v1api20220301/storage/server_farm_types_gen.go index b63dfc4f2ee..278300d7363 100644 --- a/v2/api/web/v1api20220301/storage/server_farm_types_gen.go +++ b/v2/api/web/v1api20220301/storage/server_farm_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (farm *ServerFarm) SetConditions(conditions conditions.Conditions) { farm.Status.Conditions = conditions } +var _ configmaps.Exporter = &ServerFarm{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (farm *ServerFarm) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if farm.Spec.OperatorSpec == nil { + return nil + } + return farm.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &ServerFarm{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (farm *ServerFarm) SecretDestinationExpressions() []*core.DestinationExpression { + if farm.Spec.OperatorSpec == nil { + return nil + } + return farm.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &ServerFarm{} // AzureName returns the Azure name of the resource @@ -160,6 +183,7 @@ type ServerFarm_Spec struct { KubeEnvironmentProfile *KubeEnvironmentProfile `json:"kubeEnvironmentProfile,omitempty"` Location *string `json:"location,omitempty"` MaximumElasticWorkerCount *int `json:"maximumElasticWorkerCount,omitempty"` + OperatorSpec *ServerFarmOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -307,6 +331,14 @@ type KubeEnvironmentProfile_STATUS struct { Type *string `json:"type,omitempty"` } +// Storage version of v1api20220301.ServerFarmOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type ServerFarmOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.SkuDescription // Description of a SKU for a scalable resource. type SkuDescription struct { diff --git a/v2/api/web/v1api20220301/storage/server_farm_types_gen_test.go b/v2/api/web/v1api20220301/storage/server_farm_types_gen_test.go index 8010b7b62bb..77c99aa2afb 100644 --- a/v2/api/web/v1api20220301/storage/server_farm_types_gen_test.go +++ b/v2/api/web/v1api20220301/storage/server_farm_types_gen_test.go @@ -560,6 +560,61 @@ func AddRelatedPropertyGeneratorsForServerFarm(gens map[string]gopter.Gen) { gens["Status"] = ServerFarm_STATUSGenerator() } +func Test_ServerFarmOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of ServerFarmOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForServerFarmOperatorSpec, ServerFarmOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForServerFarmOperatorSpec runs a test to see if a specific instance of ServerFarmOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForServerFarmOperatorSpec(subject ServerFarmOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual ServerFarmOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of ServerFarmOperatorSpec instances for property testing - lazily instantiated by +// ServerFarmOperatorSpecGenerator() +var serverFarmOperatorSpecGenerator gopter.Gen + +// ServerFarmOperatorSpecGenerator returns a generator of ServerFarmOperatorSpec instances for property testing. +func ServerFarmOperatorSpecGenerator() gopter.Gen { + if serverFarmOperatorSpecGenerator != nil { + return serverFarmOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + serverFarmOperatorSpecGenerator = gen.Struct(reflect.TypeOf(ServerFarmOperatorSpec{}), generators) + + return serverFarmOperatorSpecGenerator +} + func Test_ServerFarm_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -758,6 +813,7 @@ func AddRelatedPropertyGeneratorsForServerFarm_Spec(gens map[string]gopter.Gen) gens["ExtendedLocation"] = gen.PtrOf(ExtendedLocationGenerator()) gens["HostingEnvironmentProfile"] = gen.PtrOf(HostingEnvironmentProfileGenerator()) gens["KubeEnvironmentProfile"] = gen.PtrOf(KubeEnvironmentProfileGenerator()) + gens["OperatorSpec"] = gen.PtrOf(ServerFarmOperatorSpecGenerator()) gens["Sku"] = gen.PtrOf(SkuDescriptionGenerator()) } diff --git a/v2/api/web/v1api20220301/storage/site_types_gen.go b/v2/api/web/v1api20220301/storage/site_types_gen.go index f59fa20ab8b..fdd969fd0d4 100644 --- a/v2/api/web/v1api20220301/storage/site_types_gen.go +++ b/v2/api/web/v1api20220301/storage/site_types_gen.go @@ -6,6 +6,9 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -44,6 +47,26 @@ func (site *Site) SetConditions(conditions conditions.Conditions) { site.Status.Conditions = conditions } +var _ configmaps.Exporter = &Site{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (site *Site) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if site.Spec.OperatorSpec == nil { + return nil + } + return site.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Site{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (site *Site) SecretDestinationExpressions() []*core.DestinationExpression { + if site.Spec.OperatorSpec == nil { + return nil + } + return site.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &Site{} // AzureName returns the Azure name of the resource @@ -163,6 +186,7 @@ type Site_Spec struct { KeyVaultReferenceIdentity *string `json:"keyVaultReferenceIdentity,omitempty"` Kind *string `json:"kind,omitempty"` Location *string `json:"location,omitempty"` + OperatorSpec *SiteOperatorSpec `json:"operatorSpec,omitempty"` OriginalVersion string `json:"originalVersion,omitempty"` // +kubebuilder:validation:Required @@ -525,6 +549,14 @@ type SiteConfig_STATUS struct { XManagedServiceIdentityId *int `json:"xManagedServiceIdentityId,omitempty"` } +// Storage version of v1api20220301.SiteOperatorSpec +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type SiteOperatorSpec struct { + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + PropertyBag genruntime.PropertyBag `json:"$propertyBag,omitempty"` + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + // Storage version of v1api20220301.SlotSwapStatus_STATUS // The status of the last successful slot swap operation. type SlotSwapStatus_STATUS struct { diff --git a/v2/api/web/v1api20220301/storage/site_types_gen_test.go b/v2/api/web/v1api20220301/storage/site_types_gen_test.go index a663cf32a5d..3294b18449b 100644 --- a/v2/api/web/v1api20220301/storage/site_types_gen_test.go +++ b/v2/api/web/v1api20220301/storage/site_types_gen_test.go @@ -2916,6 +2916,60 @@ func AddIndependentPropertyGeneratorsForSiteMachineKey_STATUS(gens map[string]go gens["ValidationKey"] = gen.PtrOf(gen.AlphaString()) } +func Test_SiteOperatorSpec_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { + t.Parallel() + parameters := gopter.DefaultTestParameters() + parameters.MinSuccessfulTests = 100 + parameters.MaxSize = 3 + properties := gopter.NewProperties(parameters) + properties.Property( + "Round trip of SiteOperatorSpec via JSON returns original", + prop.ForAll(RunJSONSerializationTestForSiteOperatorSpec, SiteOperatorSpecGenerator())) + properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) +} + +// RunJSONSerializationTestForSiteOperatorSpec runs a test to see if a specific instance of SiteOperatorSpec round trips to JSON and back losslessly +func RunJSONSerializationTestForSiteOperatorSpec(subject SiteOperatorSpec) string { + // Serialize to JSON + bin, err := json.Marshal(subject) + if err != nil { + return err.Error() + } + + // Deserialize back into memory + var actual SiteOperatorSpec + err = json.Unmarshal(bin, &actual) + if err != nil { + return err.Error() + } + + // Check for outcome + match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) + if !match { + actualFmt := pretty.Sprint(actual) + subjectFmt := pretty.Sprint(subject) + result := diff.Diff(subjectFmt, actualFmt) + return result + } + + return "" +} + +// Generator of SiteOperatorSpec instances for property testing - lazily instantiated by SiteOperatorSpecGenerator() +var siteOperatorSpecGenerator gopter.Gen + +// SiteOperatorSpecGenerator returns a generator of SiteOperatorSpec instances for property testing. +func SiteOperatorSpecGenerator() gopter.Gen { + if siteOperatorSpecGenerator != nil { + return siteOperatorSpecGenerator + } + + generators := make(map[string]gopter.Gen) + siteOperatorSpecGenerator = gen.Struct(reflect.TypeOf(SiteOperatorSpec{}), generators) + + return siteOperatorSpecGenerator +} + func Test_Site_STATUS_WhenSerializedToJson_DeserializesAsEqual(t *testing.T) { t.Parallel() parameters := gopter.DefaultTestParameters() @@ -3085,6 +3139,7 @@ func AddRelatedPropertyGeneratorsForSite_Spec(gens map[string]gopter.Gen) { gens["HostNameSslStates"] = gen.SliceOf(HostNameSslStateGenerator()) gens["HostingEnvironmentProfile"] = gen.PtrOf(HostingEnvironmentProfileGenerator()) gens["Identity"] = gen.PtrOf(ManagedServiceIdentityGenerator()) + gens["OperatorSpec"] = gen.PtrOf(SiteOperatorSpecGenerator()) gens["SiteConfig"] = gen.PtrOf(SiteConfigGenerator()) } diff --git a/v2/api/web/v1api20220301/storage/structure.txt b/v2/api/web/v1api20220301/storage/structure.txt index b51e7d091d9..59b6e1539d2 100644 --- a/v2/api/web/v1api20220301/storage/structure.txt +++ b/v2/api/web/v1api20220301/storage/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-03-01" ServerFarm: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (24 properties) +├── Spec: Object (25 properties) │ ├── AzureName: string │ ├── ElasticScaleEnabled: *bool │ ├── ExtendedLocation: *Object (2 properties) @@ -24,6 +24,10 @@ ServerFarm: Resource │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string │ ├── MaximumElasticWorkerCount: *int +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PerSiteScaling: *bool @@ -121,7 +125,7 @@ ServerFarm: Resource └── ZoneRedundant: *bool Site: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (36 properties) +├── Spec: Object (37 properties) │ ├── AzureName: string │ ├── ClientAffinityEnabled: *bool │ ├── ClientCertEnabled: *bool @@ -171,6 +175,10 @@ Site: Resource │ ├── KeyVaultReferenceIdentity: *string │ ├── Kind: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (3 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ ├── PropertyBag: genruntime.PropertyBag +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── OriginalVersion: string │ ├── Owner: *genruntime.KnownResourceReference │ ├── PropertyBag: genruntime.PropertyBag diff --git a/v2/api/web/v1api20220301/storage/zz_generated.deepcopy.go b/v2/api/web/v1api20220301/storage/zz_generated.deepcopy.go index 9779f40b6fc..166feb93d41 100644 --- a/v2/api/web/v1api20220301/storage/zz_generated.deepcopy.go +++ b/v2/api/web/v1api20220301/storage/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package storage import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -2002,6 +2003,50 @@ func (in *ServerFarmList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerFarmOperatorSpec) DeepCopyInto(out *ServerFarmOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerFarmOperatorSpec. +func (in *ServerFarmOperatorSpec) DeepCopy() *ServerFarmOperatorSpec { + if in == nil { + return nil + } + out := new(ServerFarmOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerFarm_STATUS) DeepCopyInto(out *ServerFarm_STATUS) { *out = *in @@ -2246,6 +2291,11 @@ func (in *ServerFarm_Spec) DeepCopyInto(out *ServerFarm_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServerFarmOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -3229,6 +3279,50 @@ func (in *SiteMachineKey_STATUS) DeepCopy() *SiteMachineKey_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SiteOperatorSpec) DeepCopyInto(out *SiteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.PropertyBag != nil { + in, out := &in.PropertyBag, &out.PropertyBag + *out = make(genruntime.PropertyBag, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SiteOperatorSpec. +func (in *SiteOperatorSpec) DeepCopy() *SiteOperatorSpec { + if in == nil { + return nil + } + out := new(SiteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Site_STATUS) DeepCopyInto(out *Site_STATUS) { *out = *in @@ -3632,6 +3726,11 @@ func (in *Site_Spec) DeepCopyInto(out *Site_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SiteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/api/web/v1api20220301/structure.txt b/v2/api/web/v1api20220301/structure.txt index 2045e09860e..b599fc9fcd7 100644 --- a/v2/api/web/v1api20220301/structure.txt +++ b/v2/api/web/v1api20220301/structure.txt @@ -5,7 +5,7 @@ APIVersion: Enum (1 value) └── "2022-03-01" ServerFarm: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (22 properties) +├── Spec: Object (23 properties) │ ├── AzureName: string │ ├── ElasticScaleEnabled: *bool │ ├── ExtendedLocation: *Object (1 property) @@ -21,6 +21,9 @@ ServerFarm: Resource │ │ └── Reference: *genruntime.ResourceReference │ ├── Location: *string │ ├── MaximumElasticWorkerCount: *int +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PerSiteScaling: *bool │ ├── Reserved: *bool @@ -114,7 +117,7 @@ ServerFarm: Resource └── ZoneRedundant: *bool Site: Resource ├── Owner: resources/v1apiv20191001.ResourceGroup -├── Spec: Object (34 properties) +├── Spec: Object (35 properties) │ ├── AzureName: string │ ├── ClientAffinityEnabled: *bool │ ├── ClientCertEnabled: *bool @@ -171,6 +174,9 @@ Site: Resource │ ├── KeyVaultReferenceIdentity: *string │ ├── Kind: *string │ ├── Location: *string +│ ├── OperatorSpec: *Object (2 properties) +│ │ ├── ConfigMapExpressions: *core.DestinationExpression[] +│ │ └── SecretExpressions: *core.DestinationExpression[] │ ├── Owner: *genruntime.KnownResourceReference │ ├── PublicNetworkAccess: *string │ ├── RedundancyMode: *Enum (5 values) diff --git a/v2/api/web/v1api20220301/zz_generated.deepcopy.go b/v2/api/web/v1api20220301/zz_generated.deepcopy.go index e275b0c412e..1a823c63fc3 100644 --- a/v2/api/web/v1api20220301/zz_generated.deepcopy.go +++ b/v2/api/web/v1api20220301/zz_generated.deepcopy.go @@ -12,6 +12,7 @@ package v1api20220301 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "k8s.io/apimachinery/pkg/runtime" ) @@ -1678,6 +1679,43 @@ func (in *ServerFarmList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServerFarmOperatorSpec) DeepCopyInto(out *ServerFarmOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerFarmOperatorSpec. +func (in *ServerFarmOperatorSpec) DeepCopy() *ServerFarmOperatorSpec { + if in == nil { + return nil + } + out := new(ServerFarmOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServerFarm_STATUS) DeepCopyInto(out *ServerFarm_STATUS) { *out = *in @@ -1915,6 +1953,11 @@ func (in *ServerFarm_Spec) DeepCopyInto(out *ServerFarm_Spec) { *out = new(int) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(ServerFarmOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) @@ -2856,6 +2899,43 @@ func (in *SiteMachineKey_STATUS) DeepCopy() *SiteMachineKey_STATUS { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SiteOperatorSpec) DeepCopyInto(out *SiteOperatorSpec) { + *out = *in + if in.ConfigMapExpressions != nil { + in, out := &in.ConfigMapExpressions, &out.ConfigMapExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } + if in.SecretExpressions != nil { + in, out := &in.SecretExpressions, &out.SecretExpressions + *out = make([]*core.DestinationExpression, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(core.DestinationExpression) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SiteOperatorSpec. +func (in *SiteOperatorSpec) DeepCopy() *SiteOperatorSpec { + if in == nil { + return nil + } + out := new(SiteOperatorSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Site_STATUS) DeepCopyInto(out *Site_STATUS) { *out = *in @@ -3252,6 +3332,11 @@ func (in *Site_Spec) DeepCopyInto(out *Site_Spec) { *out = new(string) **out = **in } + if in.OperatorSpec != nil { + in, out := &in.OperatorSpec, &out.OperatorSpec + *out = new(SiteOperatorSpec) + (*in).DeepCopyInto(*out) + } if in.Owner != nil { in, out := &in.Owner, &out.Owner *out = new(genruntime.KnownResourceReference) diff --git a/v2/cmd/controller/app/setup.go b/v2/cmd/controller/app/setup.go index 5d2672e9571..5e83d531db8 100644 --- a/v2/cmd/controller/app/setup.go +++ b/v2/cmd/controller/app/setup.go @@ -44,6 +44,7 @@ import ( asometrics "github.com/Azure/azure-service-operator/v2/internal/metrics" armreconciler "github.com/Azure/azure-service-operator/v2/internal/reconcilers/arm" "github.com/Azure/azure-service-operator/v2/internal/reconcilers/generic" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/internal/util/interval" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/internal/util/lockedrand" @@ -52,7 +53,22 @@ import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" ) -func SetupControllerManager(ctx context.Context, setupLog logr.Logger, flgs *Flags) manager.Manager { +type Runnable struct { + mgr manager.Manager + + // toStart must not block + toStart []func() +} + +func (r *Runnable) Start(ctx context.Context) error { + for _, f := range r.toStart { + f() + } + + return r.mgr.Start(ctx) +} + +func SetupControllerManager(ctx context.Context, setupLog logr.Logger, flgs *Flags) *Runnable { scheme := controllers.CreateScheme() _ = apiextensions.AddToScheme(scheme) // Used for managing CRDs @@ -212,7 +228,15 @@ func SetupControllerManager(ctx context.Context, setupLog logr.Logger, flgs *Fla setupLog.Error(err, "Failed setting up readyz check") os.Exit(1) } - return mgr + + return &Runnable{ + mgr: mgr, + toStart: []func(){ + // Starts the expression caches. Note that we don't need to stop these we'll + // let process teardown stop them + clients.expressionEvaluator.Start, + }, + } } func getMetricsOpts(flags *Flags) server.Options { @@ -301,13 +325,15 @@ type clients struct { armConnectionFactory armreconciler.ARMConnectionFactory credentialProvider identity.CredentialProvider kubeClient kubeclient.Client + expressionEvaluator asocel.ExpressionEvaluator log logr.Logger options generic.Options } func initializeClients(cfg config.Values, mgr ctrl.Manager) (*clients, error) { armMetrics := asometrics.NewARMClientMetrics() - asometrics.RegisterMetrics(armMetrics) + celMetrics := asometrics.NewCEL() + asometrics.RegisterMetrics(armMetrics, celMetrics) log := ctrl.Log.WithName("controllers") @@ -334,6 +360,16 @@ func initializeClients(cfg config.Values, mgr ctrl.Manager) (*clients, error) { positiveConditions := conditions.NewPositiveConditionBuilder(clock.New()) + expressionEvaluator, err := asocel.NewExpressionEvaluator( + asocel.Metrics(celMetrics), + asocel.Log(log), + ) + if err != nil { + return nil, errors.Wrap(err, "error creating expression evaluator") + } + // Register the evaluator for use by webhooks + asocel.RegisterEvaluator(expressionEvaluator) + options := makeControllerOptions(log, cfg) return &clients{ @@ -341,6 +377,7 @@ func initializeClients(cfg config.Values, mgr ctrl.Manager) (*clients, error) { armConnectionFactory: connectionFactory, credentialProvider: credentialProvider, kubeClient: kubeClient, + expressionEvaluator: expressionEvaluator, log: log, options: options, }, nil @@ -355,6 +392,7 @@ func initializeWatchers(readyResources map[string]apiextensions.CustomResourceDe clients.credentialProvider, clients.kubeClient, clients.positiveConditions, + clients.expressionEvaluator, clients.options) if err != nil { return errors.Wrap(err, "failed getting storage types and reconcilers") diff --git a/v2/internal/controllers/cel_configmap_export_test.go b/v2/internal/controllers/cel_configmap_export_test.go new file mode 100644 index 00000000000..2c2f976a9eb --- /dev/null +++ b/v2/internal/controllers/cel_configmap_export_test.go @@ -0,0 +1,235 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +package controllers_test + +import ( + "testing" + + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + containerserviceold "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20210501" + managedidentity "github.com/Azure/azure-service-operator/v2/api/managedidentity/v1api20230131" + "github.com/Azure/azure-service-operator/v2/internal/testcommon" + "github.com/Azure/azure-service-operator/v2/internal/util/to" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" +) + +func Test_CELExportConfigMap(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + configMapName := "my-configmap" + principalIdKey := "principalId" + + mi := &managedidentity.UserAssignedIdentity{ + ObjectMeta: tc.MakeObjectMeta("mi"), + Spec: managedidentity.UserAssignedIdentity_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + OperatorSpec: &managedidentity.UserAssignedIdentityOperatorSpec{ + ConfigMapExpressions: []*core.DestinationExpression{ + { + Name: configMapName, + Key: principalIdKey, + Value: "self.status.principalId", + }, + { + Name: configMapName, + Value: `{"greeting": "hello", "classification": "friend"}`, + }, + }, + }, + }, + } + + tc.CreateResourceAndWait(mi) + tc.Expect(mi.Status.TenantId).ToNot(BeNil()) + tc.Expect(mi.Status.PrincipalId).ToNot(BeNil()) + + // The ConfigMap should exist with the expected value + tc.ExpectConfigMapHasKeysAndValues( + configMapName, + "principalId", *mi.Status.PrincipalId, + "greeting", "hello", + "classification", "friend") +} + +func Test_CELExportConflictingConfigMaps_Rejected(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + configMapName := "my-configmap" + principalIdKey := "principalId" + + mi := &managedidentity.UserAssignedIdentity{ + ObjectMeta: tc.MakeObjectMeta("mi"), + Spec: managedidentity.UserAssignedIdentity_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + OperatorSpec: &managedidentity.UserAssignedIdentityOperatorSpec{ + ConfigMapExpressions: []*core.DestinationExpression{ + { + Name: configMapName, + Key: principalIdKey, + Value: "self.status.principalId", + }, + { + Name: configMapName, + Value: `{"greeting": "hello", "classification": "friend"}`, + }, + }, + ConfigMaps: &managedidentity.UserAssignedIdentityOperatorConfigMaps{ + PrincipalId: &genruntime.ConfigMapDestination{ + Name: configMapName, + Key: principalIdKey, + }, + }, + }, + }, + } + + err := tc.CreateResourceExpectRequestFailure(mi) + tc.Expect(err).To(MatchError(ContainSubstring(`cannot write more than one configmap value to destination Name: "my-configmap", Key: "principalId", Value: "self.status.principalId"`))) +} + +// Test_CELExportConflictingConfigMaps_MapsConflictBlockedAtRuntime ensures that +// if the CEL output is a map, conflicts are blocked at runtime. Note that this is not possible +// to block at webhook time because doing so in general would require us to evaluate the CEL expression, which +// we cannot always do. For example, the status fields may be empty at webhook time, but the CEL map may be based on +// status fields. +func Test_CELExportConflictingConfigMaps_MapsConflictBlockedAtRuntime(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + configMapName := "my-configmap" + + mi := &managedidentity.UserAssignedIdentity{ + ObjectMeta: tc.MakeObjectMeta("mi"), + Spec: managedidentity.UserAssignedIdentity_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + OperatorSpec: &managedidentity.UserAssignedIdentityOperatorSpec{ + ConfigMapExpressions: []*core.DestinationExpression{ + { + Name: configMapName, + Value: `{"greeting": "hello", "classification": "friend"}`, + }, + { + Name: configMapName, + Value: `{"greeting": "goodbye", "classification": "everybody"}`, + }, + }, + }, + }, + } + + tc.CreateResourceAndWaitForFailure(mi) + + // We expect that the actual underlying Azure resource was created + tc.Expect(mi.Status.TenantId).ToNot(BeNil()) + tc.Expect(mi.Status.PrincipalId).ToNot(BeNil()) + + ready, ok := conditions.GetCondition(mi, conditions.ConditionTypeReady) + tc.Expect(ok).To(BeTrue()) + tc.Expect(ready.Status).To(Equal(metav1.ConditionFalse)) + tc.Expect(ready.Severity).To(Equal(conditions.ConditionSeverityError)) + tc.Expect(ready.Reason).To(Equal(conditions.ReasonAdditionalKubernetesObjWriteFailure.Name)) + + // This should contain details about both key collisions -- note that these errors can come in any order so we don't assert + // a particular order. + tc.Expect(ready.Message).To(ContainSubstring("key collision, entry exists for key 'greeting' in Data")) + tc.Expect(ready.Message).To(ContainSubstring("key collision, entry exists for key 'classification' in Data")) + + tc.DeleteResourceAndWait(mi) +} + +func Test_CELExportInvalidExpressionConfigMap_Rejected(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + mi := &managedidentity.UserAssignedIdentity{ + ObjectMeta: tc.MakeObjectMeta("mi"), + Spec: managedidentity.UserAssignedIdentity_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + OperatorSpec: &managedidentity.UserAssignedIdentityOperatorSpec{ + ConfigMapExpressions: []*core.DestinationExpression{ + { + Name: "my-configmap", + Key: "principalId", + Value: "self.status.principalId + 10", + }, + }, + }, + }, + } + err := tc.CreateResourceExpectRequestFailure(mi) + tc.Expect(err).To(MatchError(ContainSubstring(`failed to compile CEL expression: "self.status.principalId + 10": ERROR: :1:25: found no matching overload for '_+_' applied to '(string, int)'`))) +} + +// Test_CELExportConfigMapPropertyOnDifferentVersion tests that a field which was removed in a later version +// can still be used in the expression on the old version of the resource. This relies on dockerBridgeCidr in +// managedCluster which doesn't actually do anything now but is good enough for our test purposes. +func Test_CELExportConfigMapPropertyOnDifferentVersion(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + tc.AzureRegion = to.Ptr("westus3") // TODO: the default test region of westus2 doesn't allow ds2_v2 at the moment + + rg := tc.CreateTestResourceGroupAndWait() + + configMapName := "my-configmap" + + cluster := &containerserviceold.ManagedCluster{ + ObjectMeta: tc.MakeObjectMeta("mc"), + Spec: containerserviceold.ManagedCluster_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + DnsPrefix: to.Ptr("aso"), + AgentPoolProfiles: []containerserviceold.ManagedClusterAgentPoolProfile{ + { + Name: to.Ptr("ap1"), + Count: to.Ptr(1), + VmSize: to.Ptr("Standard_DS2_v2"), + OsType: to.Ptr(containerserviceold.OSType_Linux), + Mode: to.Ptr(containerserviceold.AgentPoolMode_System), + }, + }, + Identity: &containerserviceold.ManagedClusterIdentity{ + Type: to.Ptr(containerserviceold.ManagedClusterIdentity_Type_SystemAssigned), + }, + NetworkProfile: &containerserviceold.ContainerServiceNetworkProfile{ + DockerBridgeCidr: to.Ptr("172.17.0.1/16"), // This field doesn't do anything + }, + OperatorSpec: &containerserviceold.ManagedClusterOperatorSpec{ + ConfigMapExpressions: []*core.DestinationExpression{ + { + Name: configMapName, + Key: "cidr", + Value: "self.spec.networkProfile.dockerBridgeCidr", + }, + }, + }, + }, + } + + tc.CreateResourceAndWait(cluster) + + // The ConfigMap should exist with the expected values + tc.ExpectConfigMapHasKeysAndValues( + configMapName, + "cidr", "172.17.0.1/16") +} diff --git a/v2/internal/controllers/cel_secret_export_test.go b/v2/internal/controllers/cel_secret_export_test.go new file mode 100644 index 00000000000..9ed56565c7e --- /dev/null +++ b/v2/internal/controllers/cel_secret_export_test.go @@ -0,0 +1,207 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +package controllers_test + +import ( + "testing" + + . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + containerserviceold "github.com/Azure/azure-service-operator/v2/api/containerservice/v1api20210501" + managedidentity "github.com/Azure/azure-service-operator/v2/api/managedidentity/v1api20181130" + storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20230101" + "github.com/Azure/azure-service-operator/v2/internal/testcommon" + "github.com/Azure/azure-service-operator/v2/internal/util/to" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" +) + +func Test_CELExportSecret(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + secretName := "my-secret" + + // Create a storage account and export the secret + acct := newStorageAccount20230101(tc, rg) + acct.Spec.OperatorSpec = &storage.StorageAccountOperatorSpec{ + SecretExpressions: []*core.DestinationExpression{ + { + Name: secretName, + Key: "key1", + Value: `secret.key1`, + }, + }, + } + + tc.CreateResourceAndWait(acct) + + // The secret should exist with the expected value + tc.ExpectSecretHasKeys(secretName, "key1") +} + +func Test_CELExportConflictingSecrets_Rejected(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + secretName := "my-secret" + secretKey := "key1" + + // Create a storage account and export the secret + acct := newStorageAccount20230101(tc, rg) + acct.Spec.OperatorSpec = &storage.StorageAccountOperatorSpec{ + SecretExpressions: []*core.DestinationExpression{ + { + Name: secretName, + Key: secretKey, + Value: `secret.key1`, + }, + }, + Secrets: &storage.StorageAccountOperatorSecrets{ + Key1: &genruntime.SecretDestination{ + Name: secretName, + Key: secretKey, + }, + }, + } + + err := tc.CreateResourceExpectRequestFailure(acct) + tc.Expect(err).To(MatchError(ContainSubstring(`cannot write more than one secret to destination Name: "my-secret", Key: "key1", Value: "secret.key1"`))) +} + +func Test_CELExportInvalidExpressionSecret_Rejected(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + secretName := "my-secret" + + // Create a storage account and export the secret + acct := newStorageAccount20230101(tc, rg) + acct.Spec.OperatorSpec = &storage.StorageAccountOperatorSpec{ + SecretExpressions: []*core.DestinationExpression{ + { + Name: secretName, + Key: "key1", + Value: `self.spec.sku.allowSharedKeyAccess`, // this key doesn't exist + }, + }, + } + + err := tc.CreateResourceExpectRequestFailure(acct) + tc.Expect(err).To(MatchError(ContainSubstring(`denied the request: failed to compile CEL expression: "self.spec.sku.allowSharedKeyAccess": ERROR: :1:14: undefined field 'allowSharedKeyAccess'`))) +} + +// Test_CELExportConflictingSecrets_MapsConflictBlockedAtRuntime ensures that +// if the CEL output is a map, conflicts are blocked at runtime. Note that this is not possible +// to block at webhook time because doing so in general would require us to evaluate the CEL expression, which +// we cannot always do. For example, the status fields may be empty at webhook time, but the CEL map may be based on +// status fields. +func Test_CELExportConflictingSecrets_MapsConflictBlockedAtRuntime(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + rg := tc.CreateTestResourceGroupAndWait() + + secretName := "my-secret" + + mi := &managedidentity.UserAssignedIdentity{ + ObjectMeta: tc.MakeObjectMeta("mi"), + Spec: managedidentity.UserAssignedIdentity_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + OperatorSpec: &managedidentity.UserAssignedIdentityOperatorSpec{ + SecretExpressions: []*core.DestinationExpression{ + { + Name: secretName, + Value: `{"greeting": "hello", "classification": "friend"}`, + }, + { + Name: secretName, + Value: `{"greeting": "goodbye", "classification": "everybody"}`, + }, + }, + }, + }, + } + + tc.CreateResourceAndWaitForFailure(mi) + + // We expect that the actual underlying Azure resource was created + tc.Expect(mi.Status.TenantId).ToNot(BeNil()) + tc.Expect(mi.Status.PrincipalId).ToNot(BeNil()) + + ready, ok := conditions.GetCondition(mi, conditions.ConditionTypeReady) + tc.Expect(ok).To(BeTrue()) + tc.Expect(ready.Status).To(Equal(metav1.ConditionFalse)) + tc.Expect(ready.Severity).To(Equal(conditions.ConditionSeverityError)) + tc.Expect(ready.Reason).To(Equal(conditions.ReasonAdditionalKubernetesObjWriteFailure.Name)) + + // This should contain details about both key collisions -- note that these errors can come in any order so we don't assert + // a particular order. + tc.Expect(ready.Message).To(ContainSubstring("key collision, entry exists for key 'greeting' in StringData")) + tc.Expect(ready.Message).To(ContainSubstring("key collision, entry exists for key 'classification' in StringData")) + + tc.DeleteResourceAndWait(mi) +} + +// Test_CELExportSecretPropertyOnDifferentVersion tests that a field which was removed in a later version +// can still be used in the expression on the old version of the resource. This relies on dockerBridgeCidr in +// managedCluster which doesn't actually do anything now but is good enough for our test purposes. +func Test_CELExportSecretPropertyOnDifferentVersion(t *testing.T) { + t.Parallel() + tc := globalTestContext.ForTest(t) + + tc.AzureRegion = to.Ptr("westus3") // TODO: the default test region of westus2 doesn't allow ds2_v2 at the moment + + rg := tc.CreateTestResourceGroupAndWait() + + secretName := "my-secret" + + cluster := &containerserviceold.ManagedCluster{ + ObjectMeta: tc.MakeObjectMeta("mc"), + Spec: containerserviceold.ManagedCluster_Spec{ + Location: tc.AzureRegion, + Owner: testcommon.AsOwner(rg), + DnsPrefix: to.Ptr("aso"), + AgentPoolProfiles: []containerserviceold.ManagedClusterAgentPoolProfile{ + { + Name: to.Ptr("ap1"), + Count: to.Ptr(1), + VmSize: to.Ptr("Standard_DS2_v2"), + OsType: to.Ptr(containerserviceold.OSType_Linux), + Mode: to.Ptr(containerserviceold.AgentPoolMode_System), + }, + }, + Identity: &containerserviceold.ManagedClusterIdentity{ + Type: to.Ptr(containerserviceold.ManagedClusterIdentity_Type_SystemAssigned), + }, + NetworkProfile: &containerserviceold.ContainerServiceNetworkProfile{ + DockerBridgeCidr: to.Ptr("172.17.0.1/16"), // This field doesn't do anything + }, + OperatorSpec: &containerserviceold.ManagedClusterOperatorSpec{ + SecretExpressions: []*core.DestinationExpression{ + { + Name: secretName, + Key: "cidr", + Value: "self.spec.networkProfile.dockerBridgeCidr", + }, + }, + }, + }, + } + + tc.CreateResourceAndWait(cluster) + + tc.ExpectSecretHasKeys(secretName, "cidr") +} diff --git a/v2/internal/controllers/controller_resources.go b/v2/internal/controllers/controller_resources.go index c6436d5d433..245acb51a94 100644 --- a/v2/internal/controllers/controller_resources.go +++ b/v2/internal/controllers/controller_resources.go @@ -39,6 +39,7 @@ import ( postgresqlreconciler "github.com/Azure/azure-service-operator/v2/internal/reconcilers/postgresql" "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/internal/resolver" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" @@ -55,10 +56,18 @@ func GetKnownStorageTypes( credentialProvider identity.CredentialProvider, kubeClient kubeclient.Client, positiveConditions *conditions.PositiveConditionBuilder, + expressionEvaluator asocel.ExpressionEvaluator, options generic.Options, ) ([]*registration.StorageType, error) { resourceResolver := resolver.NewResolver(kubeClient) - knownStorageTypes, err := getGeneratedStorageTypes(schemer, armConnectionFactory, kubeClient, resourceResolver, positiveConditions, options) + knownStorageTypes, err := getGeneratedStorageTypes( + schemer, + armConnectionFactory, + kubeClient, + resourceResolver, + positiveConditions, + expressionEvaluator, + options) if err != nil { return nil, err } @@ -157,6 +166,7 @@ func getGeneratedStorageTypes( kubeClient kubeclient.Client, resourceResolver *resolver.Resolver, positiveConditions *conditions.PositiveConditionBuilder, + expressionEvaluator asocel.ExpressionEvaluator, options generic.Options, ) ([]*registration.StorageType, error) { knownStorageTypes := getKnownStorageTypes() @@ -186,6 +196,7 @@ func getGeneratedStorageTypes( kubeClient, resourceResolver, positiveConditions, + expressionEvaluator, options, extension, t) @@ -199,6 +210,7 @@ func augmentWithARMReconciler( kubeClient kubeclient.Client, resourceResolver *resolver.Resolver, positiveConditions *conditions.PositiveConditionBuilder, + expressionEvaluator asocel.ExpressionEvaluator, options generic.Options, extension genruntime.ResourceExtension, t *registration.StorageType, @@ -208,6 +220,7 @@ func augmentWithARMReconciler( kubeClient, resourceResolver, positiveConditions, + expressionEvaluator, options.Config, extension) } diff --git a/v2/internal/controllers/recordings/Test_CELDifferentVersionOrSomething.yaml b/v2/internal/controllers/recordings/Test_CELDifferentVersionOrSomething.yaml new file mode 100644 index 00000000000..574dd2c9005 --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELDifferentVersionOrSomething.yaml @@ -0,0 +1,2396 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-xqcjqc","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 1bc417a452eb85b2d3f8ea7e327934030841afc41d672d0fcaafb4fca56909c4 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc","name":"asotest-rg-xqcjqc","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 4AD198FB39C9475183D9A6BB0926C003 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:48Z' + status: 201 Created + code: 201 + duration: 180.978111ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc","name":"asotest-rg-xqcjqc","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 2D9BA3F709C641A4964F65D60FBA3DA8 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:48Z' + status: 200 OK + code: 200 + duration: 35.665142ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 249 + uncompressed: false + body: '{"error":{"code":"ResourceNotFound","message":"The Resource ''Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh'' under resource group ''asotest-rg-xqcjqc'' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "249" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: B9CF2738055C4E938FCB06EC0D795EB1 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:52Z' + status: 404 Not Found + code: 404 + duration: 47.397556ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 375 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"identity":{"type":"SystemAssigned"},"location":"westus2","name":"asotest-mc-jkjmfh","properties":{"addonProfiles":null,"agentPoolProfiles":[{"availabilityZones":null,"count":1,"mode":"System","name":"ap1","nodeLabels":{},"nodeTaints":[],"osType":"Linux","tags":{},"vmSize":"Standard_DS2_v2"}],"dnsPrefix":"aso","identityProfile":null,"privateLinkResources":null},"tags":{}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "375" + Content-Type: + - application/json + Test-Request-Hash: + - 15b5f0c4faf2b5b730c902862704dc94eee4ec09cfd929058fc77c2e35c61e3f + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh?api-version=2021-05-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 1962 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh", + "location": "westus2", + "name": "asotest-mc-jkjmfh", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-2ngofbk1.hcp.westus2.azmk8s.io", + "azurePortalFQDN": "aso-2ngofbk1.portal.hcp.westus2.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "tags": {}, + "nodeLabels": {}, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + } + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "39724cdc-1bd0-4ebf-b3c9-c3b8de81b4ec", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Azure-Asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + Cache-Control: + - no-cache + Content-Length: + - "1962" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: A3E4FFD23DD049ECA93229317B03E6B4 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:52Z' + status: 201 Created + code: 201 + duration: 5.595933303s + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5F021049A482494F9088D6501CBB7064 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:05Z' + status: 200 OK + code: 200 + duration: 76.185695ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 927849DD615447219145FB61AD069BD0 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:10Z' + status: 200 OK + code: 200 + duration: 133.552469ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 665029464F0C4FF2B750988E0EE78725 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:18Z' + status: 200 OK + code: 200 + duration: 102.056333ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4A3FF1DA33B74EF084F914F45186DCC5 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:34Z' + status: 200 OK + code: 200 + duration: 62.908886ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 34296ED8D8A84DFDAA2C713B4F06924E Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:32:06Z' + status: 200 OK + code: 200 + duration: 66.4867ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 923F25380B1A4B2C9415BFE623C4A0E3 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:33:06Z' + status: 200 OK + code: 200 + duration: 78.509935ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 22865B5591CB4C75BA9B0BEF7E077E9A Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:34:07Z' + status: 200 OK + code: 200 + duration: 67.79163ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/44d8fb79-07f6-4bea-b4be-20a9b72417cb?api-version=2016-03-30&t=638657370583139632&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0COKOA18Kn4uzwEuDpX0Wy-D3yrL--6OYVHYxFK1EgvkMMOJ_-gzKggOT8mrKK3NXwnLzgysa0AscdY2uuzYKbjklBSJZyGu9WQu0qoiy5ig4DLYYA9T-uSMIz-WYa1woLDE8uxix8M7cstR2Y-p3YfVbRm2cgYICYBU9Q3fK-tl1LzZewyaT7o9xSxDqv1UhLU_SAGCeaJmXPDWsMlCBRDtTq9U59tpu0ZXjfNj53xF2JDmFu9QfM9BbfoxAhZMcwxkUOPR9LJY8-DrY8_cfBSyleM9fiKUXdb9ufP2qRNpnirwgfsUFVBSLjvbMYNvSd-tE_wEzavbh2RysyjUzw&h=xX9yEuQ96YUj0JD5quwvMbW9o-jAKPxoQr3taewytHA + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 165 + uncompressed: false + body: |- + { + "name": "44d8fb79-07f6-4bea-b4be-20a9b72417cb", + "status": "Succeeded", + "startTime": "2001-02-03T04:05:06Z", + "endTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "165" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: B3E4FDE69C684F83A1113F168E2C4937 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:07Z' + status: 200 OK + code: 200 + duration: 56.620119ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh", + "location": "westus2", + "name": "asotest-mc-jkjmfh", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-2ngofbk1.hcp.westus2.azmk8s.io", + "azurePortalFQDN": "aso-2ngofbk1.portal.hcp.westus2.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2/providers/Microsoft.Network/publicIPAddresses/7fe79490-dfba-436b-bfd3-2a1b6faff7cf" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-jkjmfh-agentpool", + "clientId": "05cbc969-89ad-41db-b4f6-8a43e42b7a81", + "objectId": "b8cf2404-1a7b-4bc3-a408-98a1b5775e94" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "39724cdc-1bd0-4ebf-b3c9-c3b8de81b4ec", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 66ED7340907041E7923F4AE77616B8DC Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:07Z' + status: 200 OK + code: 200 + duration: 405.666252ms + - id: 13 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh", + "location": "westus2", + "name": "asotest-mc-jkjmfh", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-2ngofbk1.hcp.westus2.azmk8s.io", + "azurePortalFQDN": "aso-2ngofbk1.portal.hcp.westus2.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2/providers/Microsoft.Network/publicIPAddresses/7fe79490-dfba-436b-bfd3-2a1b6faff7cf" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-xqcjqc_asotest-mc-jkjmfh_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-jkjmfh-agentpool", + "clientId": "05cbc969-89ad-41db-b4f6-8a43e42b7a81", + "objectId": "b8cf2404-1a7b-4bc3-a408-98a1b5775e94" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "39724cdc-1bd0-4ebf-b3c9-c3b8de81b4ec", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D8C9958992344E87B7CCA0C4F5A5973E Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:08Z' + status: 200 OK + code: 200 + duration: 418.016379ms + - id: 14 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: A5858181CBF04A88BE6C01BAF23CA896 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:12Z' + status: 202 Accepted + code: 202 + duration: 171.641063ms + - id: 15 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373274285493&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=PiPWUhxhcLBAwhX7BMYht9_OFZvaj9sAELXrXxktE5zMF3-qf9pIHfKrT_vwqnIyg7m0XzI7BdCaKt3DzsBzhXrXZ_6DmmAqEhEanwA4KKVQYIVP-4UPS0m1aMkpuMjqfCaPMp_Bh3YTkot6r3E5Qf34XroqyZfz2OCEL9r1akfo6RsN0YS8e7NwlGJosB2rqIWLfz6c179cFCG23-AzD9eQXavaK4IFBqGX6bKx2PwBv-FNBW-C1OBDTUrdl3h-mUGHJLjo4ILQ4USN7Q2Or0IhcCcIxALWThKS4YjgcFol_cOW4bf0TG5V_1VB9fs04JLnDWkBCs_iLSeMIp9X4w&h=myEYwLklUHXIE6tPBX1rjVbPyD9CJSft25m8guTGiXo + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 9A7CED8C2A874874ACAAE3CD5930F563 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:27Z' + status: 202 Accepted + code: 202 + duration: 52.066012ms + - id: 16 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373425069898&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=afJ4iBl1ZrNcwgG1SVJfsJLYLZREJ03sZmRjC37xYTRYwnP8_nFskQvGlthLDdnG1PH6F7fTK8yrJZ84BAl_82S55j3gMOajFhnKLcyQlZbdBt8DStNcS5vJ_OdPOEYLhh1SGyv8cyjLqsRhOydliL5xV0jnCGGY9NKHlz-rOxfgPNrYadV-1LXiTtHfUnUmcaH-tsko6WbXezSfqUoKUSXA9OkG9Na2n572BPQowL0ZmnNofCey2GrWLyo2itqJvdvFqUJBXzvXkFQ8N9-3KOBG-0q4Jpf4nr8sgsKAo8tpLJ9LdG5y1rb4G-cSjSIqSxa9JzYpomx1a-_ZRMwXzg&h=UIx0LxoCTZ58uvJalGJ9XTIsZqMdU0tk2HdrZs5-1wU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: BF6848890F104CAA95231544C251616A Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:42Z' + status: 202 Accepted + code: 202 + duration: 45.5318ms + - id: 17 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373576188852&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=wlEOnmnJxhJrVFJs-KdpW5k4-sJB1SlAoSsjLSg6WeH24VpFrMg1Mb8pE4UR-rLeXSPQpjuoHjUhx2aXGP7cSthhhh0ciA7LuFFdl8k3pd5epHkHsL1rEBvsaxOr_1MN4hZXdTh3HqyMPwny6y59JtwZel-MCIqQ-Bpn1eQ6vz6_PT1VWH6KUC1RgxWbDaPdd1Og_yaH3VJHk-5xVYw8yJ4_0O-pLKRertDps1setit6FQCX8sVy190RwoCE44BM0VxU0kK1H9wOIgPrdpCsZkI0SDzJwTK482xnL3DeVzGBqyuRV58Ur2VDxZlAJFiUSUrnONVuqvehSxt1dgaYtA&h=1WW3QQVvpogxzaQV23XKfzed8lkbyFAtoumHDqKKoMk + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 575CD50D283C4674947650EEFB2B8F7D Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:35:57Z' + status: 202 Accepted + code: 202 + duration: 35.93798ms + - id: 18 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373726964200&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=HnHJklb9yUpqfCX9G56AlEjxJSTJsGvGqluCx_MWYBdo2BgT3ZbV1pC_YSi1zBzJJHGqtq7uP4PQSJNUJVugAa3nJ_940kqkF44lkUffxQ8QlLixy1NG4IWGkHq9H1_e6HqMKe6RxAVxOKPh7WYej-E4vneEztgYnjaObzt-YsGc7oJ5wNSRwMwlCyQH28Joyg1uV7JVTHvtoxhr-jSkPvm8WixUpOaYsF8iJcSuHuZTe5CNBwrlzGtufONVvbL6KdCrOOk6Ih68p9YrKQlY18Mssh_38ud-8-1xjCAl_qoxTnnGU9kFxhW57V9us7iHhbocyu3PgTR1FBRX9_r7Vw&h=lVp8K4gZrYlkSGGVIWhDLUBitm-04d9tBpxPENwNfUU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 2629272277E04472B3642A7610D44B91 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:36:12Z' + status: 202 Accepted + code: 202 + duration: 32.919974ms + - id: 19 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373877837070&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=PP1TpKvbZhTb98QceNjc0wt7zoeta9jCh-LEN8QFmObXP2S5JaUwZM6zefEY_WLcVueUaYE-KnmzWFXT0JTUfcaRf8uJxWC_X2tvlqGMfRRlO73isgc6pbNDFQynPcCkKa9SEAvLN1OZwr0Sci-pGG1pRXsrLnd1GQ2eecmLp7OsNyQEfmPNvLJpynniGirjDCPYnDSp1_gxaKytrdyzFodSiD-9V8Rux0xqFCQoCkgUkSjmAYU0Ov4NsckV1fbhA2vQDofaGllYyFeMiCl7eGo_PGyDU55M9UT5pPIVm19avVFoW76XVb9nfxEjrjh3XbREtXQlIby7VmwhdmQyQA&h=SgYgjnQsygaoI9ij6CzsZXEw6iS287BK4MvpFlVoUCQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 497DC7BF0E3140EA9D6435551C4093BC Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:36:27Z' + status: 202 Accepted + code: 202 + duration: 37.673387ms + - id: 20 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374028600385&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=6xUZy6b2RaI_mKFO_pOndlCP2kPMgNeJTD15QAUaek04froPM2-YBGNyw7DQb7ZdnRGNqmY36tsbOIlC-LTloibmFWE27k_imsdBW9CpTIqG14uWWjOnXiHwKO-v71q9p6FWdEaQHf_9mU2tS1yVZ-QLp2_ua8SityRSMehK1TB0R6uV-Vul9xnohet0wkQOerKRIuVfxNbI6QEiZQmIY043gnpF0HVkcCqgALlw4J-SjA5kpMV8x-VPKvWNmfODD1j4LsmBchik59Zj5WIR8geuG0VC02CUlqL3VEctXnoL1IWvAmlNqce-JbLtzSElC_gnFqMIGFcbKpfSR_BRRg&h=Ka6VS9WtYoye-HN_-teTmEej15Leh74FrbJEOf2-vfc + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 09E8C0FFD537408284C2D609EDBF1CC7 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:36:42Z' + status: 202 Accepted + code: 202 + duration: 33.044378ms + - id: 21 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374180180284&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=sAHqZ8V0ILEfxInvr068mSNOmm7EjLm5GOQB8OcYVJdyJOPwkWOvENrgsq5p-TB7skXd0WEw4tcauUVvCd50w7l4WwRgUVtzd9pSWNZQ_w9Tb4wCYk1amZ7EFtP4aONeM96tHJVOfuNMx3n2ZDpodl6wc5L7m_KZmcZjrGARnrmuM3eIJ9MGEZJGipffCtZkdapML_BXDL86K_KBloEkh2Wm3YAvqZiWXIwB7fy1zUxDLcfGUi15ynQ2_kdlq9Z8gS9CLo5DltwtZAiFKXmJ2nDEdafWqvwHqzdWduGamC3pExgJrelEx1v5ejS0lZXHCddJxukYLZvx4cJ6-WaWoA&h=eQcd30hGsDXSrQM_JY27klhSgUf9Rk0hgqqvc0CXbPA + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 92BF474A5D3B45E9A945768C6764DA89 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:36:57Z' + status: 202 Accepted + code: 202 + duration: 127.342202ms + - id: 22 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374331991975&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Hm6VCyZcublVeBz8BDdWhEPEFhMpx6Hcb1V3KL0F0EBk9LBMrWkH1JtZQjeLdo_-3XYTWKKGFonsO1tglmrcrNFllnZkkh6ZzZABc3sh1MONqcTPd00a96JLUBoOfQ6gaKtzGr5z12CX6ArFPpEnCKUNr9i2FiwkVrP1OrHKXcJLx2jw66QXF7shWR-87G6ZJbyxYrwehNIxXxKZkNxKSEts379wInf4cK9z_q4LffqV3kD6xX72s5FjoRzeH6GLrKcVkaFaucGRAEg1H7lv00MgO03N-GYOSG7pfGlsWC0Y4zw3C4H_FT26Af1N9VelndaqSulE_AVbL6zziwHu7g&h=_e7cMy02xidZSEmTL0KiHPW9ulXjRFmPaMJiCgW8dZQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 1F929F03BD6D44BE9160566909A9C101 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:37:13Z' + status: 202 Accepted + code: 202 + duration: 40.533298ms + - id: 23 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "8" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374482990494&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=nIYUCZtwaGP3oiurq6omptIsHiPraigGuWzQt0KmD3Cu_E7XTP9zQvSvwifvpAC7OlHrD9jqLgWceC0SvwQ6YaramgqUofFo6_3WxBZ0vbO_xM7YYM3-rBEsZy8XgNH-FBikFoFwhyRpss427PuT312cfnbyhYGSmiVfIs06duHBrjcKzgkxW4ksQb8cGamMyzuMvljShQb_01XE9704zAwWcrKPpAQMqlvyoaq8arTEXPA7NtAosJD2xh5pKNVkIqBNwW6_u8W_AflQj_gozftg14Oa0FNrM11Ft2wMLuj1g2FYMJag9rHX-v7Qp3YTqPCCwQD3W0jAsHIXKyXUSw&h=7uu4DNE4_srSYRZ6AgnOHSN6vFJJ-ZrvezehREu0as8 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5105C5ADCA6D47749364FC923C4AF038 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:37:28Z' + status: 202 Accepted + code: 202 + duration: 66.771862ms + - id: 24 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "9" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374634396774&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=3DChegJz7OAg_CiXcHYRULMWtjPsHzo6OFwhETXf2SnAqmRx-0t5Wmbyme0iRxqFCyOGUoC1myENCRujvnf-GyLmkJ4jejSpOCM9qyStnmXNLyBj5-evkaVWbi5NASCzLTxqiZr3kxmKkq8kQJ8ArJrFB2drNilR2VJy-rR03YDYpZqk5fy1ONYTJTfNkUWz2H3uxgYq5zi1M_cC1KNUKWZtmbJz-1D0bsdMaEKCrMM1UtTCSlk4j6auXudlTyZY513SdfSFr4r7GgNtjsPUtcG_sqKGcyLhrzJafE7ZeXG0M4Nvs_-tPmgcDGXUij85Q1m6Oi8gPXMq7qsUPHiLiQ&h=Akp9CzflTF2gu6cH60pvJHGLZ1krycSM8fit8lLn6Ew + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8270206C8CEA4824AFEB3957DA1E1316 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:37:43Z' + status: 202 Accepted + code: 202 + duration: 37.977494ms + - id: 25 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "10" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374785855550&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=azHwy6Hq1LmyWOWNXx9qQ5qacTwHu-dsnMwZ28PacIRVXjjUYvSVoKp2eTLbO4xHydkFQ4ef6BCELQor4YK9pSBYVHOhKPiNRff_pyX605Wy3dYNv_1YhXtP3gTKIeM3xcb6-jVyQFQtA70EEoDnf88e1GmeU7_I53MECo8BNyAGg5n3uBuSkIRY5l4sYsEabfU-QkdPrmoFLeheEvcliG8rjWCwvu5FuZNa1xPNP9QgPU0MEPaEmW3zqgBZ5WtywKV_v0vMzkqNCD0U6La2huP_6-U9HVXGSF9q2LSik4bqM25VRpuo8lulExZhGUDPPdf9XVG2dt-1x7vOOsM-LA&h=Lgsw6d5o0yqpL6aTmS623lX9pDoxHFMOiX9I-9HU30w + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5E9B3F61A5664544A8D99025C1D90530 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:37:58Z' + status: 202 Accepted + code: 202 + duration: 105.072262ms + - id: 26 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "11" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657374937334202&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=1BkOZAwY8ZbqDwUjoZk-2i7VlNKlR8X5jk5mD25x-O5i3vvnWhE4Cc0yaNoKDF23JSZs3LMJqcU3Q7eZNk6cJ1E-scinv6_GxhVAPiNg5LvpNu2URWDPaRxxeiV1ErH3pzGy3NuP0HvTpRoMb2a4YIpW7OY2ZGsOjuZ0rfLEHUxi7fewPvM5aaOoK33sgWsAnewJ1PrPi_bdWu1Y8FSTAYxaczJL7rPeHnOMMqfyd--A-Hl746ufTPABuJjxNKk7tPatJaoJ6iSWwATV2WM1vx0fD_PlQro0eLoKXy6vfs_rqoFiKhMtP1uf2MdN6EkY0CQYi4GWnLiI2vSg-3Cy9w&h=eXKHDfjmztdyRMMZsNntckfzdp_pE0-kYdwYMaB1Au0 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: A54F826CEF714EBD9E1219E725B86250 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:38:13Z' + status: 202 Accepted + code: 202 + duration: 31.67208ms + - id: 27 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "12" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375088074648&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=8SIOPkyDlO5Qth6sXRNY5oef5MU-8Bq9IX0g0N4ti95wVy-RhusI1ww8SnRHGVpfZKgu3vtxjri3lQjoTWuYYRBTz9fxAmS6qVppdDcdWHEVyQFzcXGZGigq6J2vXhriySfe3FLOBlooQCrbDjL6DLC0qwsjpbuohjPnNfE-kalvtgaVCCVVJ96l7lJiB1kzvbhj1k6GKSVKI90aiA-whpQNCPb_hocMfzFqYBqZmOQooF3GofGA42jze7uiXA4QcOnq-KxKnrxM3KZGa-LlZgpBOTct9T8uA1GZoCJDmgzhYdU1c2y5JSef0BphI0W7DCCjMYUR8mhE1g6L0-0c8A&h=O6s_3dtwmoQOMpfNcRYjwzgTAaRyr7RDyN5AdRbC4Mg + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 9CA3CF7EE8E64D0D997765B86B006FBC Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:38:28Z' + status: 202 Accepted + code: 202 + duration: 42.707009ms + - id: 28 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "13" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375239091898&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GcYzPsL-4zFEZHyQS5UxATh16LyJpq5sx5lETR2QL1N8btYblEemRHE0Vx_WygF5ZRTI40loXhtyFbNBN78xV4z4JCyZy2DZpMT7bTnoQriqzKKDUh-odyHvWBlTib5n7497QUuShRtolAhvD6hxst-Jezu2QiGJbZ_oTYqLhT1NHp69W4VjQz2ORJXiEQ8CMshDiU8s25OSl7hYrEjwnWY0--xVjgJvuQIAyICkQmmiR5bnb9J5aC0aso5aPuYR8AjjDhMvcA-xozf0tsvhFnl2qlgQfgC-H5hQShSOqr0xQXMmOyhxCZ2uOWPMEUP3uSbrnEQpd9hWBpj4E3FAPA&h=1DL33PC1DEAZSjBS4ClWIEi5q0WrpGMHUJJTASKkWM0 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 812C75F9D0FF44208FAF2D79D8E49BEA Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:38:43Z' + status: 202 Accepted + code: 202 + duration: 53.101437ms + - id: 29 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "14" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375389987592&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=YcoQMTyfGlogdJUXzYiA4HS4NVucXqZZFvGI-Y1OzWuFSP_7CXmKhCkhvnFLvwecdOIrDlKYyyQQ5L9PCIT3OamoJ3pdwW7niHSHJzyOQXLVymkAUeJgu2fg7KcxYAE68xZAJ9aBH0Xy0IpNNKh_qxPxr8oZzNDb6TqNgpDy-vo19Yp5aZB4EQWwMri4OPlOetRW2mfUZfAv9wdVLG0un2ZOHyw_6nJOYmPnye4ICPuoEMZt-HwqupLNNIsgDjqf66hVAJSl801N9lVpMuG1B-4oQEz-DItnwbQi4HwggaHPJIWouB_8aSI8ZhxGPTVT62p4BDqe9JafhKF0w9r8yg&h=A5k8g3JtDWdtGcY7WSYfL2G5MWvQFHGvWzFXzl-kMnA + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 00420872ADBA40848DC2EC2874EF7539 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:38:58Z' + status: 202 Accepted + code: 202 + duration: 27.163471ms + - id: 30 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "15" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375540765900&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=ecevbiMxYJ6r8YvK9BE66qPosYadeplFX1lpFi5Z2Y-zR7XG7nZMii246QwT_bJebH_4G1dQBNSA2qEHoxz3VcQlBvPLG9s_pxRoqdL_wKbEPsUnsO8PG88taOVTZ_9HZvhj1RX2coRsL5ZMsCiy8XQ-rzZSsloW5s8ulEMpcNGzpB-T2N5ISTa2TjNLikioc5Vaah50tyUY2URV-7F2SfJEJlFQYxxUP6ba7Gxfec8OWp-3e3RN19ViTfQ5sttkFGMxa50YcuPErFPB8eBAeNsaGH3xaLGw9Wb4xOkvxcBZHWlRrYd8Adm8bYwMMNhwIKVgN6m9Y8hgcPvXLQPOrA&h=EMa4UlnaJfexNRJXkhxZxAyGqzkQOd3FtG0JKc3irvU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 1B194A2B6F0B401E8383276E839DE8C1 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:39:14Z' + status: 202 Accepted + code: 202 + duration: 40.913208ms + - id: 31 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "16" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375691663853&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=x_IfuxiMqgAo0Iq_bgkH2_o0t58QOoyAcUPFyXspx2IT7oHKS9f_LPfbbuoPezeZGlT6c3KkV0qS2Rv3fOsNegIK0Spio8ppdaxuxeldf1rZoV55HJNlaRzQUmdCGfpjJEiTKjNtyLIUJLdqpN3o2Msn_8yha2M3B_9gM3Qp0E1FuafQzX4JRgPXwx2pgq7wyhT2loWLhksWwYs2z7-Kn-bu-id_qpoY2pwphil1HO2yACTamCsmt28iAco6o4N18ubWeI59_utb_n1qWuuqcMmS5KLlDp1T9l_-1qA6wFF1IkEDpK-da4lSpT4iGqgSBRtp1jFb4ZPk3yz8heHIyg&h=8bfMqZ0sFGK16wMXwPUEZk1iYnD9hASPhalY-COvHtE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: AA8E708E6D9F4959BCC1D48E6843468C Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:39:29Z' + status: 202 Accepted + code: 202 + duration: 39.869006ms + - id: 32 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "17" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375842679519&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LamH2KzEa28J9i1QFs6-Z8UmDgYuT2-3trtohgXjdjlosFMzNrHwoDOGxz0NmyCSjapyPP15Gdkso-sum4v-eLC7WiTm3tckCrv6rUh2DK0uJAbF4pWUOAbaKE_Yy4KPIxEoWxR8vjfI6j79IQ02Um1KGgw7yEu8so0BIy5RPs-ET1bjpEAFNljMuy_85a6F3MyaWGfLLzod7siT8GMtf_i6GmaBiMgFtlO8MqDq3jFfnOfl3X9rgAIRiiLykMfT-A8V4D_8i5EZY3lluPD7YPkAPdLHAH69v998WNvPN-NX-898dTqTsrvBzVWviS6IfrvTS8U7oR7gJosXFM-7yg&h=c_SMnbJky1e0xwiIEEbaEJcPUszqj_rr6rZ1nfXvN70 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 67C8A3C1DD22464A9B541B631EE58C5B Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:39:44Z' + status: 202 Accepted + code: 202 + duration: 52.492141ms + - id: 33 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "18" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657375993663024&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=TOwaeREw7Faup1sfoPjjx0_yOUoB4hP1_wOwA_F7pOeS9c_g7MbyZEio8m_a1wT4yc6PqqKsrfx_z8QefTO0j8WpNmVCppnYatHD54z6XE2vz2s04ruLUIvOgukClEdbpEE_Z4sW7Qdstx4T5yeC_w7TAR3IOFkIThWudLb0vWea7fsYFfhpkvkFwPkjtlisjlm3KPWjlOrT2imWJ0nsC8cyatq8_OEEEd4p_sa-ARl-jFMbSMUerGHzQ7jvm59cAtPZOP7k8WwnEicthO3oAmtlmUOuR0iSUqetITbbrFTi99twG7bvLgOXRAEoYVeXeHoE3LOOvBjsrSi_W_LNHw&h=QWQx-g1RGkKFBVmls5qVYIm-YFjWqBDCV3CluXBh_SM + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 84DC75D8040744AB849A95B9F57B5119 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:39:59Z' + status: 202 Accepted + code: 202 + duration: 33.538291ms + - id: 34 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "19" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657376144916800&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=4aa1MaOa2DI-kbHZw_97X07Km3cDf_-rgQOFKU-SWx18A31B4HSRYxXl9ivU2Z7JjbZHl4Dyuh9gLKzEBTuBx5sFEp9AHH0A_sDd0nuvQG8F82jqognjuQPfudMhysgTw4D84bx-Yo67k74lLHdWGvOkwHRSi2QFjxptCr6cDlGTGGeQCzFdUAu1KYS0symVEWGP4MQ9K-kXeR5MpxEdWGCTE_MA0EiI9De1eSUO7PHdlbo4uLIlwIgOJjneGy4RldLqiKXQcBcRRYIyelfOtvm90M8mRR8rrQqFDwDYnNWxH8nhSJXuoMmQn5Q89D58jEF87noRZd90-Xyj2z9x-Q&h=nKsomfWgz3ac9YEzPcFlWhpvl0WzPFq0IXWKxWc8jhs + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 206CF7FEF6CB47A9B3ACB382D451D77C Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:40:14Z' + status: 202 Accepted + code: 202 + duration: 103.105382ms + - id: 35 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "20" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657376296739613&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=zPWRvdf8sqSxmZWOE1my1dYCAWhUWa7vzSaxUXBWnNIMSxkUCwO68KcBY6Ys5uYzCHCGuqqIOHlj4Q2KeAr7qW8cQzoDP_ybKPBtTjnyJw7Jg1D1Ruu9L-T_s6LEXzr0pFyBmi71Bs5-MDObTHKv25O2HZKPUM3fTsCKMo5EpWKDc_FuxM09ONooekLfUi53D0fWQrwM7PRV3qyP27jAvrLoAhJ4mCFN6uIiKuN9VczIpLMCXJN2cLegBDypk5qGUGdUGXMfY8PMlwmxvw5iFzaaz3xwb2LTPpIZOc6BH179ZtVofYceBQi5yn3HcUcs-lTAuY6Lvu41lVNYzgZiOg&h=z-SVZYRapZefMOusM4qiUAZQp4zQBe48q-NuL1JYXzQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: FCD24AA0B2AB43E18C63C1638D1C60D0 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:40:29Z' + status: 202 Accepted + code: 202 + duration: 56.196955ms + - id: 36 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "21" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657376447738135&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=gUBPGzdCh82JVRXs8H183ox_umwEwqvIau04cWpWHNA8bbCxeK9_1F_0wXyR5bO-TexF5ZlKppu8FD3zCzjNzUTAcZ4Qe-ce3-ZSBkJY0hy9bmHQ9VbQtEIjimKc4Z4kikK2cA2GvmIgKAlRVYxBgGID8EcE34rpfvKMDyghPmOo4dtCDL846HPi7wPSPb8igk5ltLbbRjAuiUyFW3WQaD5oozV3DT-1akyZzvyqCwihWwh-cCaxJxy6VRi1uTpv1-8gmQY-8AscxfRObTopMr_3PTeDTLGZ9llsUdZsg3UkUi3KGc0OXkbN_T-QwParTZFA414-q6zCRzKELMbXsA&h=cwJ2r9hN64FNLAe5oUDbR-5ju1WsESatR7goQAYJ0nE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: AB0DBDCC388C47A886CBCEACFB387313 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:40:44Z' + status: 202 Accepted + code: 202 + duration: 33.880794ms + - id: 37 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "22" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657376598955153&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LkWOPkV60KAx4Zu7XfAe_slolaN6duYpYKnOcT5Imt8VfrpyC1cNd10Tkk28fCFZGhfFZXw4fsrmareeHAnQum-ZXaWLTCANpriqUI7CTadt05VIfj1nc_64YQqPDE4OFv11UR4q74BvkwrPOQ5OMF1Bb7CeGyROxVoKpTdsKKGaQw0S9mMLqMgkgi9l6Y2jxb4KjGNY2aZXQnNFKIZyLGRFMiElSFHy-JcA5TSLyr61num28nD_KhLfiqjUceC63Y2hGG-HM5xc3zNZVXKgQwyIhGJxQKgrsJuLizZy0MOgaQhFXYzpb0Axnwx2bjifyaHGZ1TJ8E7vfdm2k_9VBw&h=Z1YL9PIk73RJGf7DPM5E4uneOKMaYQTTxG8e5oqv0CU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E70A6BA4005C42FC943BD2DB68B2894C Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:40:59Z' + status: 202 Accepted + code: 202 + duration: 63.275677ms + - id: 38 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "23" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYUUNKUUMtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657373121776748&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LEdueOR1iRQkc_kJKHRI0pfJpiTV9xY1PFE8vqf2kOlH--RvdnTV378-4rP4W-eAV1mNKl87Ov9nhXucRbQzxflxOD2bHxqJWMXer8qg769cG9WNmrUMlpz_m1_YJ-2Pz1v4OKHtOIQWUAbeRdNoIXpr_a9qKR-I0UQM5bZCvxDAI7BKKe7NYj_c4mueH8mkDAaEoJTfe3wPnPcs9Cq3nQMHJb3nSX2v-fFASSzHSXBUk-MZJK23FX7KKSVncK7uE152FEvWsvjNXGb5sL4GW9NYkBxFq6T36hotn2Kyqe1epsLX-9-KemJ9lpNxOrOJiWdhBSWPUljF2uKq8vL0Tg&h=eJpEceC_oxMSjL-xwZohzHDU9hym10pD98X9TdDK7RY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 3B5DA672952540A78CFA69C4D2D3BAE2 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:41:14Z' + status: 200 OK + code: 200 + duration: 36.449103ms + - id: 39 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xqcjqc/providers/Microsoft.ContainerService/managedClusters/asotest-mc-jkjmfh?api-version=2021-05-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 109 + uncompressed: false + body: '{"error":{"code":"ResourceGroupNotFound","message":"Resource group ''asotest-rg-xqcjqc'' could not be found."}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "109" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: 4A67EEEABB904FBFA61E880AF50E7FF5 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:41:17Z' + status: 404 Not Found + code: 404 + duration: 79.024623ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConfigMap.yaml b/v2/internal/controllers/recordings/Test_CELExportConfigMap.yaml new file mode 100644 index 00000000000..7dba9b01f86 --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConfigMap.yaml @@ -0,0 +1,651 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-irrcaz","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 6bf3f93a94b370d7b8d3286daf7aaaf274b90733e0eda9fdfb7d1d301646d10f + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz","name":"asotest-rg-irrcaz","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 78A84BE28E474B8FB032330677C0C12C Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:00Z' + status: 201 Created + code: 201 + duration: 468.900238ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz","name":"asotest-rg-irrcaz","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 924D327DA27D44569DA1DA2B277DBF1E Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:01Z' + status: 200 OK + code: 200 + duration: 84.064179ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-myvgfo"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 7a0dffc7b61fef7520ec1fdbfca5d41ad0bbfeaad3e0c30a18df9a1607b6f889 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo?api-version=2023-01-31 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo","name":"asotest-mi-myvgfo","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"dd0aa73c-63db-4a91-ab98-c07a55b02a69","clientId":"bd52d211-6327-456b-8986-10d03870308f"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Location: + - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 1925633E02C04C0086F578F6A00CCD88 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:03Z' + status: 201 Created + code: 201 + duration: 1.02030477s + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-myvgfo"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 7a0dffc7b61fef7520ec1fdbfca5d41ad0bbfeaad3e0c30a18df9a1607b6f889 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo?api-version=2023-01-31 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo","name":"asotest-mi-myvgfo","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"dd0aa73c-63db-4a91-ab98-c07a55b02a69","clientId":"bd52d211-6327-456b-8986-10d03870308f"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: A0D44C8A699A45DEAE8C3388B29B330D Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:06Z' + status: 200 OK + code: 200 + duration: 219.387111ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo?api-version=2023-01-31 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo","name":"asotest-mi-myvgfo","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"dd0aa73c-63db-4a91-ab98-c07a55b02a69","clientId":"bd52d211-6327-456b-8986-10d03870308f"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 474B4D75B2F34328A357585CC9F2AAF5 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:06Z' + status: 200 OK + code: 200 + duration: 74.395671ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 54879CEF6F934131BAD9927B48B89E10 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:07Z' + status: 202 Accepted + code: 202 + duration: 330.472321ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370229054179&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=XxFo1CC75ppVhRC2dqNQFCPb2eKawbfZh5wWCPjK7oa4XJXcxt_Btg6aWLuYM80hIJsbUQPhFWjj1BeraB4Nrv6TvMxQQYs9Ya-NL9l8BOdw1CiMAygaFbxHzONbREpt2t2UXtBiLDzGmsu88nd6vIYzikIodojYRu8niCfir2d2RFlAixoOw4N9k2BfmrpPCDNrWcwxd_ZBUcDU_Ib2NS18p2CX0PVyLRiY6SihO8tZCzvBpbtWVZP2AwGFfiaip1qduaKaogTZrimjWlQIQVvjEkq7CcR_MfcPj28fPuQLKnR5muxW2Gp1asBXjMYMbExMgccw33Bmzt3sbOCXoA&h=m5KqsVPmw0nYHJFTJkyAPi0BkdAc7Ses_MhRkWSahPY + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 37EF13BAFEEC42A2BAE3F272BAA2162C Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:22Z' + status: 202 Accepted + code: 202 + duration: 46.941949ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370379983972&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=kgHgcfopiaNZbx004FEs46LnNyzzd00vY5bnGkTUBtLSmRJ5CvBO3IjWb2xjE-igEWOTguf_igw97e6oGCnE-DNEDg4AKnkV4z-Gu7CkGOYgNNd-mS_9XSBwk2UiHaQEUaiyUXRErhfi_Ugw8RT1zx1iHJ9T7SyRJ0_e3pNH8Xg9xK8g6PnI306PtQ-3FD5PCHpieQPJvbVIPvNvECgzzYoIQ1352YoPjFfAeqFogGf5-p5nHXHs_Sfiq10hyQlAqpJ4U7mlN_vyOQfWntRO5TYHOtro5QXkOhggJ-tffnzOrshnh-AO8Tsi_y2XXzO_vQkTQ-gCosKqe6bCLQLRaA&h=ONm5IdnOwxjYVyGywJTTEgzD9WTlNkI6zoP_lZOmyzw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 404375EF5BD04BCE9CA120495784ACB8 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:37Z' + status: 202 Accepted + code: 202 + duration: 44.060849ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370531250102&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=mzBPrAfzOUZIoZDiL8t7W_NXuDK0uV4nilxgVR_LBL4GBFuTx3InLz3UTA-ZqRqZRCH6oa4swBfO9Zb6DyYMkWSagUD7kFqfewnwmKuXxYbctbYWOo7ULWf9cELVm42pUYi8FfSMdWilLYk4YSCC46K3fwtQxGUHuKZU6MFvRe-uTokUloRWQVzPImJMgu3OeB_jJXDrMUAlERlrvJJF1gbb2XkkiSC9-J8ZgT023Bu1kAMJdCiuN0fA-1G5iCHiAgMSZDTSRNh23IM77WXQc08zytOi8-4v8DlsCZSZlTN8bbXoJbsFYt2dKcLmu0gy1OZXmhLjlUFzE5zSgEvilA&h=eTdpF9djTroxTgfstcMHdVSljntBeKquNNYQuNPw6zw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 38C6E48F4C6D478A85F09D517A13E7FD Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:30:53Z' + status: 202 Accepted + code: 202 + duration: 69.024582ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370682493177&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=gGVKlg-lPUJ3V5qSXT3j6LTjyZcR56cn8qqRmO3GwYANz1sFXG_dtyExxjP1iOxi-KuLtLkoh4gqbmPYQdQ3lOwE248U3r955jyzIWzXPUUfUxfHy3iErVxcu1eyk2WKxVmFO-olqxRjug35PNe36Ivr4bA1K34ZV64hQruj7fPgRqn1JpDv0h91a2CbIkLONIy51bpT4ulzIv6RR9S50jbEYDJD3pEeZjlWktAoit5qM-aNKcC1XKX5ZeLHlNbTHTzOLhEFRCkU_PCpc2SKNKVeUmZZ_vmOrjker6VPvp4UiT5516zfD1vyYeueGBKqHEFkdDYtbjYu2ri80TatVw&h=ugu9C-dRZUlqk2l15rEB3wOyICnxVFUEZRm9LUa2KjE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4339303CDC1A4DEDBEC6E6849F8DB372 Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:08Z' + status: 202 Accepted + code: 202 + duration: 44.642557ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRJUlJDQVotV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657370074725074&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=GjNzC0_O5JEEIFSpuRGul4WBBlIe4YO7kqgcU-sFwycQrUMvVvOQyj3wTYjzA3aabF44MWc1lkZE1atGEbp9PApGvlS-y6zfwm38BJtfZdcQvcUliMi6oL5lR0t3e7tG9J2NPhm7sXkEm27s3pmt-2ILdChEdWTZ07flKHBsQJS1K1FA0TleExrFZ5lCohfTyfT71Uy4ViW1BLOQBbIklSCDBplrkPIN1rSySdxVlJaAFG7spumWXwJg9oa4UH9UY7Li12-G1Fo105yBHSI7GTXRHWN6v5ZnXbRAuQtdgtug-fjKgaAJmRrygc-w72VVA7x-C_ZWywHsIvoXU6yDGg&h=sEb1fk-KVxLvdTya2Aef4fbJRLjOluRCgoPiZTIiT10 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: B0CA8BA5E46045E6865EFBED9D5D6ACB Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:23Z' + status: 200 OK + code: 200 + duration: 65.662287ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-irrcaz/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-myvgfo?api-version=2023-01-31 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 109 + uncompressed: false + body: '{"error":{"code":"ResourceGroupNotFound","message":"Resource group ''asotest-rg-irrcaz'' could not be found."}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "109" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: AD068D37A7D44822B6A3B7FB3306CF3F Ref B: CO6AA3150220029 Ref C: 2024-10-28T18:31:27Z' + status: 404 Not Found + code: 404 + duration: 88.746619ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConfigMapPropertyOnDifferentVersion.yaml b/v2/internal/controllers/recordings/Test_CELExportConfigMapPropertyOnDifferentVersion.yaml new file mode 100644 index 00000000000..8ec2980d164 --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConfigMapPropertyOnDifferentVersion.yaml @@ -0,0 +1,2396 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus3","name":"asotest-rg-yfjtxl","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - bac69e14050e6271097269484fb61370f5d4ad01426875f2b002a3f196bcd4fe + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl","name":"asotest-rg-yfjtxl","type":"Microsoft.Resources/resourceGroups","location":"westus3","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: AAD0FC4CF4354CC2B95663B391094450 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:32:59Z' + status: 201 Created + code: 201 + duration: 590.976196ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl","name":"asotest-rg-yfjtxl","type":"Microsoft.Resources/resourceGroups","location":"westus3","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 332C75F448F94D3A9E0606A05A4D60A7 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:00Z' + status: 200 OK + code: 200 + duration: 36.716068ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 249 + uncompressed: false + body: '{"error":{"code":"ResourceNotFound","message":"The Resource ''Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn'' under resource group ''asotest-rg-yfjtxl'' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "249" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: FC799F69EDD2492D966185CBAACA1EE3 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:06Z' + status: 404 Not Found + code: 404 + duration: 103.705276ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 429 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"identity":{"type":"SystemAssigned"},"location":"westus3","name":"asotest-mc-mlehhn","properties":{"addonProfiles":null,"agentPoolProfiles":[{"availabilityZones":null,"count":1,"mode":"System","name":"ap1","nodeLabels":{},"nodeTaints":[],"osType":"Linux","tags":{},"vmSize":"Standard_DS2_v2"}],"dnsPrefix":"aso","identityProfile":null,"networkProfile":{"dockerBridgeCidr":"172.17.0.1/16"},"privateLinkResources":null},"tags":{}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "429" + Content-Type: + - application/json + Test-Request-Hash: + - cfe50550b49d845e503d4eaf9576d6a600f0c16329b8922851060ed1339b33e6 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn?api-version=2021-05-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 1962 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn", + "location": "westus3", + "name": "asotest-mc-mlehhn", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-m08bj9bq.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-m08bj9bq.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "tags": {}, + "nodeLabels": {}, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + } + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "9a12f215-a692-4d94-bf53-a2d7d8b6a619", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Azure-Asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + Cache-Control: + - no-cache + Content-Length: + - "1962" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "12000" + X-Msedge-Ref: + - 'Ref A: 682E72C7D6BF4A12BABAC5AC9CA4BE06 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:06Z' + status: 201 Created + code: 201 + duration: 9.29902583s + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: CF63AE1DE04E4AE29A57FAD844D82D58 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:27Z' + status: 200 OK + code: 200 + duration: 222.574144ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4AC00FFD5F4C4F2C9DD3F3C7C5A59329 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:31Z' + status: 200 OK + code: 200 + duration: 264.692847ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 3C35B19F37A64484AE404618A6410FD7 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:40Z' + status: 200 OK + code: 200 + duration: 214.68022ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 989984A09231479FA4F88551D187F96D Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:33:56Z' + status: 200 OK + code: 200 + duration: 224.591683ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 3CE3C04BB4A74DFCA7444DA8D5A0485F Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:34:29Z' + status: 200 OK + code: 200 + duration: 110.004645ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: EC80DEB6E37746AF930FB7F36BD9CED6 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:35:29Z' + status: 200 OK + code: 200 + duration: 133.841094ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D72A1C638EBA43238FF190A58C90A43F Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:36:29Z' + status: 200 OK + code: 200 + duration: 230.078139ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/19047593-0c0d-4b5d-8134-ec80eb64a28f?api-version=2016-03-30&t=638658415961190300&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xLcowRKlQA-uX338ujh8xqt3E0D79MPVuK4WnilE8V0D3H32WwTYVWQXWIcicC96P0O_o6Y0X0d13wRMTf8U4ocidGRqA5wS_EhpwP3P-6PyxOwOxVVWw_saqDUj8MJHyZsVjV2FNGh1GphCOTg6aBlRyACfhTyRJjSAIMUs4zVYU4pvFVHm39fCMDDeuCmLYlwlKRXY7lFSVARw8wxkoZS6m8t5651xOmateWKCvg5PiUQ8swN5p-9ruYTcIW4MdZbyCLZA1qfI-VcZaC1ySKWGUchyXLIJc3l6fVv_k2NK5Ejs0Mbdgx1jrXgJfvqY6lGNa6xQize85xZWiBomzQ&h=vUC6GzffZReeJcOuY0bmUn2KaCwwbxF4GLFQr0oHce8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 165 + uncompressed: false + body: |- + { + "name": "19047593-0c0d-4b5d-8134-ec80eb64a28f", + "status": "Succeeded", + "startTime": "2001-02-03T04:05:06Z", + "endTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "165" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 45B09934BA9C4BF9B8EA23020F4BD175 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:37:30Z' + status: 200 OK + code: 200 + duration: 200.110414ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn", + "location": "westus3", + "name": "asotest-mc-mlehhn", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-m08bj9bq.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-m08bj9bq.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3/providers/Microsoft.Network/publicIPAddresses/96e96797-852a-42cd-85d3-cd256a5f1e8b" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-mlehhn-agentpool", + "clientId": "7ef82c77-73f9-4e13-98b0-d4f35de8ff35", + "objectId": "43c8393f-d519-4e22-8bd4-ae2b252d1c7c" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "9a12f215-a692-4d94-bf53-a2d7d8b6a619", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 2C798177798B40BCBF14FF5E0D4C96BC Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:37:30Z' + status: 200 OK + code: 200 + duration: 721.660921ms + - id: 13 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn", + "location": "westus3", + "name": "asotest-mc-mlehhn", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-m08bj9bq.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-m08bj9bq.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3/providers/Microsoft.Network/publicIPAddresses/96e96797-852a-42cd-85d3-cd256a5f1e8b" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-yfjtxl_asotest-mc-mlehhn_westus3/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-mlehhn-agentpool", + "clientId": "7ef82c77-73f9-4e13-98b0-d4f35de8ff35", + "objectId": "43c8393f-d519-4e22-8bd4-ae2b252d1c7c" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "9a12f215-a692-4d94-bf53-a2d7d8b6a619", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: FC63C6927CB04305B238CE81F35F666D Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:37:32Z' + status: 200 OK + code: 200 + duration: 599.463042ms + - id: 14 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 6F7CD24F4E514BDCA7FEEE56315A747E Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:37:35Z' + status: 202 Accepted + code: 202 + duration: 549.44677ms + - id: 15 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418723754847&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=HQkZGPDi1v1BJGKhvOmSnuc6Sluz9nARF5sO9ItYSnRSLAwzw6FZLvBfYLkg9vdUeCnF7R-D3jc3BSeK8wdY9LF9dIggvsT7724Dh3ITKtTSwHJDkP6OF8UK58lF2I_oFnaNaCSY3m7cEK4ONWNp7vgJm62o3NcCy_LQCj49RddayGGckyzu7YdxnzBvQ_YkeByNwym0k9MyCo93qqcVtBPXCO9dOAWJKtkRJYqRB-un7PiGxpRy36nBWtIETTcqtXi8RwOmBfTKbBY_iPF_hOntMI-RvB1mpdPpXnfDPaARp5Tgm7jbSKX9s5pdvAm2SEkwcbnUwIhod8YB6lXEHQ&h=-g3fMFIH9zAyv4a91YR3jT2F4fc2nAiHq4Y0Iu8FDp8 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 3CDA4B61DBCC4AD388DE3272F9F98E5C Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:37:52Z' + status: 202 Accepted + code: 202 + duration: 284.586803ms + - id: 16 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418879284138&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=tKyxzCiLm7g9FOy8XEyLeVrtNlKdEq0BzL6eAjlVZr4NJSJBk9hYP06XmX_2vvlcJ2LiehkEBGXN27abcc13Yh4eI3Ybzf30-Tgcj4ItdkTmswx4HEWlAHtBWO2bNaAd9OLWWu1mJXgkrp2ADcQjO7RWkddqA_zYcVuLjn-Kz2t8TKdK-vbeBV2tg74u4oaawI-GjTvDBlfkbZM6nkmEM1CwuZu8tc1RcqVovDgL7tdEPDG16RJVWLoiGisRtQ-YspIxfEGhuGO4y6ISysJFjRi4ybgmHA5hnKgURgWUp3YISgAnHya4KkTmbIDUgqhDchZ_R6vL9-gDjQ83X0nGNg&h=Ek-kFdCo07z10C92yJaWFoHuBgMhIFLQhuqANJZONyA + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 1D02B66E0A15404B821405CFFD2A7535 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:38:07Z' + status: 202 Accepted + code: 202 + duration: 255.457249ms + - id: 17 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419034388272&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=0XHiO1WqKdoA9N6LrBrWvOSiVor4J5Oeknpc_S6mpmr71apH2NetfvaDK9yXKZwM-wAM9qtPcfztbnMZkrPWs-b3G0Dn7aOEnRS6OWrwd94K2biIO1v8slTAR2r90JOGCtzSkiyVfzmYkXc6piNLSobD8bhe2wspiQWZKXuZb5JlG3jFll3Ow3sKBp2tEd0UTv6flrRXCiuanbCxMDr5VzWF9c1IJroQRkV7Ogtcpecvx5IeLXseyr8LeepazGMixzZ_PHxn4HHmU43CveZCnERxjCBDhDNrPRp2RHddXaZGpAYy4ay-YwT773yvBb-v9UadWtBzbIY5EIxi1Jm6Yw&h=ezVl2dHoRYUWRoO6Vd6HQAI9BIZuOVDP-JsDHWZaDyc + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E7FCD0B107CD4DEABA3916C27AB852B3 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:38:23Z' + status: 202 Accepted + code: 202 + duration: 244.037994ms + - id: 18 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419189572403&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=KYk-jpoN7A48liHAyit8Ad1LXreJ0ViQLn_xHPkhSyHMV4F7SpBMkSvpKEYIasjQdNJDUXvGZs26RIDff-la9ezC87yeiAHi_JioiFKkV-rJE30up9uGKMmmQnz9giub4AhJbUL-iBnzhcfmigyZLFFVVPpudrxD49XGaCvw011gCDOY0OVp5tyqcm2hfCDVaq9F5LFhbfgfZLom7JI8IXcfKZZ75GRR6Lt7yNk47qLsn8gCJ8l1wQNKbIpQwe06pN-Z45KPbDnye-B5RM_V4xXwzVDi6tuJW57aPA2iBTE0BI9PQwPG4ONIMSnfx5kLP1gcDG7PHz3-GRpth4Hn9A&h=vP9Ju8ogNt0tqr-BfZq9jgyB-bZo9zpGDnMJWnGIgWc + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: AE91E2EEB9D54FD49CDEED208668E250 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:38:38Z' + status: 202 Accepted + code: 202 + duration: 262.974612ms + - id: 19 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419345020027&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=4aL9ZV0FmunaCLxEa9FuesQ4dGf54EQ8rOQc_9rmgsnB_YAgR8E-pv438jI5U5yhct3_4fbZQlKSPyWxYwfSoP9lVe0Nsoka49SqI5KMC-Z7LEBa13nnczBYalhV_1rw3qhHEukh42OpRYHwqS-dlCuqCLIGWWS6dCebxx6Afr2TMa0nkWqhvAK_MoK2HDt4D7nZFzKnVOjCW8khFfI6Qixl6maPpGkWOU-pCsg8fW_n8yD7xXBzg-7XZ-m-3K6u_N453oILk137wJjLldmEaINI33emUnYOkMyqaNkKf5kQ2cEv89f0n55914GOEwInvAlt6QKNyHWVz1WSFyQGFw&h=sH7W9ahW59Sq4XxhHzJ4w8VvNBCuHYHCxFyNboYRYiw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5CFF4D9A5F7541D6ACDC602CC3191E35 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:38:54Z' + status: 202 Accepted + code: 202 + duration: 277.060003ms + - id: 20 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419500322419&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xWtnCIatGoV4u2wVfgSa9Xfgwf-135Z5OEXDDatRLg2qkff37YZo9Ckq0EBQlM6geiYZioExqVVPES7EO5Uj_tXJ4hr9JqRmxVdKW37nIX4BX7OKDWWsFiFQbxBNQLXgIdduO52C6hX3VpVJJA2cAkkgCKd_l2uwDdglp5_dYi9eOVBPFQvipYBIHPm80oltjF-YxpcAg-NQp6cQ4ptcUCmjvYqVOg56FrKUJdP1LP27-Xj8-9x2rAoPx9hulv42aTyaQGZ5LXYvfCEdXsV2ahJXf2RmirkPlWSq50DNlS-PRxaTgSoDS-HfIzI8XRiMgFPbVkgfD6zpNd1obfvodA&h=XtOzYSdF-UipDWWl-gbYuC7ai1tXQi63zfna2myu1iQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 0441A978808F475F8AB38BEEEAD83E15 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:39:09Z' + status: 202 Accepted + code: 202 + duration: 245.728131ms + - id: 21 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419655769491&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bpMqR6wAgdAxFfcwk2RWSB7CEqkIwnQ6DIj6lYvaWpW8ZBrDqZ8khuR5XOQOlxM1ktizsUZqbtqUsAHYK_MUgUG0AEfQjq3nLuG910riQ1zQEDxJVb8xgnnhAA8426tLq8PBO0foqHAJARNoNlc5Vr3fkoCB7EjRZa9_yIkmRFuuQa-PiajQu3FTjAdyz7W9qf0kLM78sZOr7oitUI4WIdj-4K7Ex8SP3Qh67vsuR_ZiUa7f_PFQANpGZqgxNjMsJfpXuXXUDoAZOA5arW0OW-BT6KILlBQ1l_sVtLMHsV_5UwgZYaFDAc17PjSLW-Np4YsiLwiSe9mBxBard_JYzw&h=rVCAzIKBSlE2Bt1RRb4E60AeTerCql6UgzQGCR8ULUE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: AC15AEBDA5934DC8A912D251EE675BBB Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:39:25Z' + status: 202 Accepted + code: 202 + duration: 287.785087ms + - id: 22 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419811247738&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=dKHj7ergG0RQON4t-rT84G3kazBqkMjcEMsQWK-2dBwxEhuzzTqN8EDGq2JW6yfHPsK3LUtpZtVtpuAT-C7krEcI7MOEHsXcqfWSsjSZDD1kuVgyBpTFWi8g2GLQJU0JJGVSAumbllh_6RWSCmdOJpIRGOt3O2rSkeO48HPMFqVBNySppRZXtT9ADUV89dPbbd4iqw_oG7t6go6lSThz1wznaB4oXaDTdj-xU1kEzrVSHcIHC9y85pN7FoYQLF76raSxZfKTo_gm3PhBeNyH0WSmyhXrJ-MruRmDZNcgATASQ0-oHhTlGb6yRCNTgmAE-jRUqpxZssEDV-cTJH-TWA&h=aNApIQGSba1GUBo41pYmhJ4nS58DrmReDGgZOta3EKo + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: FE7F88C9EBC14C84958297C431CF1DCB Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:39:40Z' + status: 202 Accepted + code: 202 + duration: 247.429858ms + - id: 23 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "8" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658419966498123&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=622YkujbP8o-WN8MpJB3dmtgLfRCfdmdIgtnuXyg70xUhQFTtKqlnFm_CIA8NoPuFs3VWqdcpJFSbcqw7m2Xbu6upMA6q-8HWjVRm8IIPPNTf0dFlDKF4NhNwSxwiFSSgDzS5gXY004X5UsKwgAqoLoaOlqBEFSZ33G1c6BQQ7KDy50mCddckrLWezzhigTQ0KziONddrea11f1GHLyU78PiytCJSSs0CSohbHzFjIKvhjAdDQiyopnXc8uhjoaka-HuHLmZwe6f_hG2CF2GbT8Vsqt6mm2CMZaEwQXPuTCuMMJc67-UIU4wdznhfNG692cO0LcDOtartAbb2fXaEw&h=Fub5BkMtQMnhQBD8M2POol3kflYuT8uNucMuHlXx5cE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 86FBFF51656845C6932424BAD740D86C Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:39:56Z' + status: 202 Accepted + code: 202 + duration: 278.650452ms + - id: 24 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "9" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420122437324&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=mSkMk-Wg63ExcxaVjcsP7d9MiRtUjHkWiMc1kEx5naMeDtsA-6sRCWRqp-xGFjJePevYCGaZ1O3068mFS18G8nyyNtm5S3nuMpboKJzoWKtvmoPNqnqTXZ7yB6VI5dS1aALcd1YGE55INVmPPrZYPwxFkgEqCZtCH7bsUlP0c9JGdFaHQv049dWHjI3elo9C-4OSMPQKDP9AUI0PCxl6SF-iuBQJClNOKjSokPT6KX6AMKr5XrYqn5yYpX7tG5JKnBsrZ8mVpdf32tBd6_HWAK7hnf6GR0dkMldAj6ZDA21k9OWWhulM3weWB3KGI4lrrPbHeitnh-l4hqPpHabpxw&h=sKw87U5lCLRT1lM6c7T9FsywVQ-bA5JKDZrs76UeokA + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 27C96E2625E343AF976FC6C75A1E18B1 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:40:11Z' + status: 202 Accepted + code: 202 + duration: 296.497867ms + - id: 25 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "10" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420276943118&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=o4ZzRR8q336jcUR6wU6cZ78kpwnzZD-SJoPdbnLAyIYcqVH09RPMsmJ_AvFL9PvR47V2Vm5D9eSrhVysQrVb5IdBCUebhXJYejJbXD8LIUuDkDt6XEzEfpB2jWjI84ItUkHPAt-K4HhSXjhx8sfEqccZn1b-kc10C6YQagSKNP6lBqAC4hgH25BT_ZOy29U4wU2vqbZ9BS_lkwgjnut2l2i6qhg6MbUMKc-So01yQsrjGZAMlctSNU9FKmxaCuazxlFtak2hB93iJ0EEUqQaCAKPqnQbsksF7mYmMhJDGAHl5z1VTSU2n3DzOoVR35hlLr159mY0YVB5zoQpSltweA&h=NWY1vU-92vimwlZbEKTiCgRVtZusqExqrwcchB2BuxU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 96FFAE1343BE47B0961E5E5736F019BD Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:40:27Z' + status: 202 Accepted + code: 202 + duration: 151.522008ms + - id: 26 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "11" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420431191320&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=AJKOsbHV_yq5_ZUQyf-m62ME3ob9Ps01laz_UWQZskY3xxzmRw_xr4EFLerUymCo_vrMVYp13y1ALG1JjPcPUxhOT60Xz7fwwXYeaw_qkK_Us9331BWz5WYTfhTa0sz2s7sS-AY_YlxdU4TUz8NKGZps7IcbtCyFbVQynI5yha8_GHh36PFp6nMHQOs-14kHimMayYnjSamAr-8Evv2Si-YtflV8ivlgs1zSbCuNvN0Ok-WL5wx-v5CwXdMA5JnIApNeIjniJcmagig18kvZaKLNZ_VRNaOj4tw-qmmAQB80MI8uk49jc6Az1bBwz7NdRUuMRUUaOospnlPaYIWWbA&h=7abVHAv90Wg-TO4O_GbjB5fb4RWj60dTKCu9aqywLQM + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5921875B51D844E6A5B8744728C3923A Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:40:42Z' + status: 202 Accepted + code: 202 + duration: 266.098803ms + - id: 27 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "12" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420587446125&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=LZ3evSoV784HwDU2TVXbteTSk5_T0Aljm1XoViG3vz_eGXVO0tw5pwxZGwOiMAoHcOuNj5342GEq1FJShMyZTi2aCEnDDU9UVRlHoIIsbBmUmwX_smUHDMmWqyX7AL4H_qLBA3Z0oXWXHYkrrp9MW7O2ukSMrdtwpWqMWVwPMhnEZGYn63CfCG19WBnVVguV3JFlRx3KhXRJt93MnrypVLwvcEPncwsUd5VIG_V_E0svmPqrCP0DcCivoKejiJkggs29zzzAniWhbYQBfvsc8qyEv8-wFj1agsp-eJeRzPy1wsBwMNcw9PUh6mvHDNlp45TCPV1GHnZTMr4L7Tngpw&h=22dbbuL_ljEiCwACQpw48oOx8YhlGVCV4-Cd1Q_1N0Y + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: FD33542964BB458C890C6F64E192A33C Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:40:58Z' + status: 202 Accepted + code: 202 + duration: 358.809672ms + - id: 28 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "13" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420743944272&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=fRm8pz8QtEvE0zpNdlp4RlAsQAyIYJe9jnldruEgzHkmxvIWG9BsyYX-uG8fKfPOuILLNvi8Lr0e6u40rK9nf6TQSUhmN5kV9cY1YBm4hVK_GY32HW9rO2aVxpupsUqaZqJUyq6uzoM9l7mZTmUGh7xIYzan796BHmt1Iobrc_Cjhq0-BP-Yva54ztR6m1zZlzW0Dv0VNBQjRF7nvznWjCvOQa-myX1oDr0N2tARInniGU8wvvls3sYQmvuLuWqzwzjkkR41gqtUJIOixIeo1wntaEGmjgePW8k7j2IMF3NopRyTycWyvMOLaDN8VIrOWo7_dRmV8LS118tJPqe61A&h=EbIaz3LRMOLZ3lMn7V_gxmEihmZj51fP7Qstbkk49BE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8986E32CFDFC489CBADF5A8081D29E00 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:41:14Z' + status: 202 Accepted + code: 202 + duration: 269.49134ms + - id: 29 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "14" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658420899146290&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=kdWkJF6KKvTQgSOUUCInNW36T7FTvsbsyB1VceRhGobZu_XLYTBU-OBzK74go0K9e5hZSuCYxloAaZY2eVo0OCeNO_BtFM0fc4arpKe9ET4a7I8yIx_xQI6mAWbxfdPkdoBR_Oe-OHa_ayePsxGXxsv95_7WNvJwjNuo8Ujgl0ctT-Tbe-_c5rnEXO1zd7Avc-U0S0f4V8yeYQZ9MW0x50ill2MrCv-oA-v-WUg78k3s1J9KPWK1Efq23cq9CpkVqQRHFUQT45DaeWOnfnOBtMSewjl5ll-N_5R4jJtda4Uz3xqMT0WYKBy8dQSJfy7PfGmIUX9VDthK60lgnr2opQ&h=3Mo9viji4Sx7ZL0JKGuKfgSTjgW6OPeWXMc2dhF8WXg + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 3382195FA9C94CBBAD7F8630A7D56F57 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:41:29Z' + status: 202 Accepted + code: 202 + duration: 244.689495ms + - id: 30 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "15" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421054439035&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Nx2yBAooue-oxlBHfNm-e8ZKTZPBo8h3nTEmU1Ci0wFQviA5aIMwpsXEsiTijDvcsz-WgAIXZcQOgeHEKTa_p3jnfAKubdzsk2a60FkoTxr-vsNsLNn7nuEplmxqYLpEINIwfFlJ3nbMi8GQ-IXxZNSG60CpEAclxtvOy2Qvy_7WjboP9shxANLV5_pSh_2lo1GfttcpHgfO10nIHAlDTXMPR_fGyQwfw-3H1f1ins8N6nPLcIhikW43DPNjp0PTTlfkVo1Jv_Ff-WVLF0v9fE2S3ts-mX0cTzUzItSInyCSg97HbSSxXRpoXkGXyEOjxqwzUIIMxf1u-AtndT4Xbg&h=yjdOLeWUFJTAqPxtpG70hWTzlgcTgtncil0v90QrFVk + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 139F1F444B9045F89B362241AB9CA1A0 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:41:45Z' + status: 202 Accepted + code: 202 + duration: 297.454826ms + - id: 31 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "16" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421210080981&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=gN7hhATTQQjSnmg-n_Tsp3u-hIZL7Lyxgz_a5IEjtZDDPu99mpbk64l-JJzuWh1bQAbCzerKf7z9Q6waTDBOeREisC13p7lCAGVqCgapNdKKMRUOfR0FuyyeFNdowHihOgdimfAfIE0rP5zXBbztFd8c0rfZNL9YrIMwifI4xhU4hqNNynWEJ5HKzJ3IL43iyEOcIiIu_t697NXA8QvpGB_pJehcJrlTE3RICpXFdrIChDTZr3IYmzJWWbjgrzAfMkFtVHmx5uZpmUuWL_bCuCvuN2UW26D00a-bIaK5TZQkZDCS7TI4B6Ep_uSxLADx3_7MrDUlNRheGUOwoA6PKw&h=_V56mZ5ukY4o5Qg2KWC9F3Tj3djFBM7TMJ6sVSdb15E + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: AED987B2918D498A93235E256EF4319F Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:42:00Z' + status: 202 Accepted + code: 202 + duration: 245.696814ms + - id: 32 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "17" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421365302348&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=M5aX5s7hrmu8-MK1jMVA_ZNdNC-fYgXS0KdYF5zAGZMWfu4mQ4CTUhrOb29lU0O0lyU57lFP4o2s44-jObF95LqWNX6CPPPXOghjAyTkIWCz19e7JZ6Px5QVCnOOE8pkKErb8xwFECTq7G1jx0BpvNfAYXtzuEJrSdoHTCDA9iQtWSU1JweMfKBOkhAC8nifcKsY4AXOfnbbXeRZWjUk7jgj6E-_hs_r-Z6qULkOYrxA_uQm6oXQPrZ9FHwtZu9U3nf5r2WJZ4tH2_FFDt98ezu9H3FHX_kkDWIGMfwl-MbhnCRo0D8P149w7qRFnF2A80g6ad8hiVRmzREyldkVCw&h=pStZreEuzMjA4D8nCdBw2TmFtFvzxpe_AGBFp5UmHKc + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D67150345CFF4F178601BBEBCF6C852E Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:42:16Z' + status: 202 Accepted + code: 202 + duration: 268.259961ms + - id: 33 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "18" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421520500918&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=mbbfWy_mGs-WMjcOTfIOJU21amXYoi0YtgTLA_E1G4IP4kAF7SVTCSr3bH4in0foLiNJvgPrWQoPbdnTP_L0KBLN5BJWQu8pM9KuoGqDfBbxnsUW_l0EVprlU72i7ZO3aZEWN93B9EczucyyTZk0rc0Ze8StutF4RFTI72PiZ-PHi6DkG6hQxihHOSa4ZHIzz5PBMlI6dPAa4E2SMprU8sDYUw4Qrq_g0Y3goAHFLzlx9xbpaNJC2SdzLLIZzD_ZLnyuOuUh9iPZylWV4ICxZrMsfe50MMmHkagHHf_FTG-5yq8UCIm9So1ECAzbztHd-YVgJnfaKTE6sXZZzjwacg&h=8ACcP6Do0rDbF4Gj9ymvqP-ZxOD4lYWUfS3VJuQCio4 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D95E7ACA3B134526A256167449E9D7F3 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:42:31Z' + status: 202 Accepted + code: 202 + duration: 245.348224ms + - id: 34 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "19" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421675786762&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=Pfcrpb1U5eqUJcJ_j6qz2fDukUjQw2wqvqVcCRnuIQfqGKvRbvnN85Scbh26ysrkv3hjO0T50QovSmwdHI7L5I-4-N-aEbJIuVnoqUmN5lzJf1zj_MrrYYhVi4gcQ_oIQW4x2BPiiXXMgctoCSDebJCW2dpiZLnpWkiSE71ebafTBusvR7qvfOf2yNEmxOmszbG3X2ieYZ2MFpeoUSwt21NCmq3Ub07AP3sqRu9WkQ5q4K1CnwED3oFAx2ULKvtpK9rctPMrZOXxJUyzgWIsf5oh7_SRXl9oaR9txLMsGUy3svyv7dsBZfmDXa_Ss813ZIMFoAoHQEGctQknBh1DUg&h=5m_ow5XLzZoI2ynDr-yYnOjKjjuI82Bp36RJJ-RUIIs + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 0A82544DC5C241B4ABBAE935DA006346 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:42:47Z' + status: 202 Accepted + code: 202 + duration: 275.496219ms + - id: 35 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "20" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421831142073&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=tN86fE4XUafJU8hXjzVuX_BA9OxTAwPWvWhDXnPSbSgnyUqrh8QhYPGmyiT6DWY3DJ-ZYH9679tSw0r5q_DOYm1ODGq7d4kAI7sN-TEogppz4hKiV9YStalCsDQSXooJaXajp8YbFiT6jlOFKchNCXH7sm__yOBu0xXP5K06VI_k9eRJgWD-JxsOM587q06dp7BEIsPkcpjLNZY2jN1Ad_m8AbEKK-ZesE9gVPl38OKur30VZRxSUrS3_MLLto0txQ414kx5R2AeSc__YJ5QgfCccfx9GsRZ17Q-g9GYoY0ojxcxa34KZCAkIgPKEyfatCn5k_YmSjwuojMZJ5P1eA&h=J_6MZm5zRgeSNEsz_9S2a9hvocOTFZzN-rgM2XG4hw8 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5454EB71EC694A9C879AC68FCD14A767 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:43:02Z' + status: 202 Accepted + code: 202 + duration: 247.341349ms + - id: 36 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "21" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658421986577813&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bo5FyYZn7LNhIEkKFLzKRsVkzlWE2Bs6np5WvA-ntnODkIFanSdsnrQOrBksqArNAoSVYgLq41gG5ltPJY2aOggQqXErZKdy8hT8fb5YSoZpvyotZHXuPNU583bBHHGXgNex5XCEWcEKcm5aIZ7NGycemVl0HWF2SQUvqkj3GiznIZfGNLmiPY-xG0z1o-tFEjLZJ0nhXcyLkD7sGNdHcBsK1rhKpRXRoSAWknnZ1s1Sdm4kNrYkCJ70oB2f84qFkfmSjUBZ02s4zvVsx3ySTa3QGifitZySMVP2Dg0-v8iHIquFD5HGrb_BH68w5kFR0oQN0p38YidBBYNruro2Cg&h=gthO3oGjUNPIv_J-gUYjOs5R6y9AV0B9T2k6_cRn8zI + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8E0D6E434F554582B654D5715872E87A Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:43:18Z' + status: 202 Accepted + code: 202 + duration: 292.698439ms + - id: 37 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "22" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658422141008661&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=c1YHGffdMwcNYq67TF4a8MLl3TjxxZ5Ty2tuC6rd7szG3YwvIdyZ4p-d0SI3tRrXBQV3WIqm0RHeyYpHEIx7JY3qCDQaP5u5x5FggX8HghLOLdAOAeIQ652eVfmQEHL_mLzitiIggOZEqJB3pGDaU_RO36IurvsMxHunKT8146D-v1115n-RN44nSuBaELWq2d37Qfb7K0rQgdK7WXwFBO3_zlmE9NnWE_qAIvOQGGV1pHmSuS5iOMePxHFMTggQrKsgYs-ADQcC9xD4uLm8W2KcEsFdxQ0-Zl4WOvS1XcLboH9tAr27nNY8yaOlF25uHv3wrhXQTYjjFD79Urz0aQ&h=jzVLLFQFsl403mIJmQ0soSAhQfsqVOe2XcEDszt1RbY + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E57F5392703B4B80A8A4262C35F10793 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:43:33Z' + status: 202 Accepted + code: 202 + duration: 150.392448ms + - id: 38 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "23" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRZRkpUWEwtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658418565040264&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=bMynd7jAlf_nkTW1plWdB-jeRzQxC4kgvwBiexdKvlr-9kU-mKYcbQQ9fUB9l6YA9ku9ExlW1YByWazGwQUOWjKYLEbipw_N5J7DTRLlN9ofbaexaN0aUI06MoEvXCvG_xbdipKbItIFVaZlduP7lEJQrb8YyQRpyIu-6qPwzbs1ja4fth7dk0c5vqE3VtkDZp7gyBbors2bYpITH8R7StmGYMB-ZW1PGKVaQeJ2G6M0Mqwo4QsgMZEgEhPwIaZ-KZxw06NaHaJoyCui748KFioqbEyX7nwLtdhWG3V6kyZPzWWkCo_mdJxCwUuqiJm-cbt6mcUZIPleyaIq3iXy5A&h=g3ZUMChKTGQGHbba5zKgksK8nYImjdMPSxb41mjeetE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: C72FCAF92D82428FA5BBAE6DB92A65DA Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:43:49Z' + status: 200 OK + code: 200 + duration: 238.494809ms + - id: 39 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-yfjtxl/providers/Microsoft.ContainerService/managedClusters/asotest-mc-mlehhn?api-version=2021-05-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 109 + uncompressed: false + body: '{"error":{"code":"ResourceGroupNotFound","message":"Resource group ''asotest-rg-yfjtxl'' could not be found."}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "109" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: 8A7E7EF882DC41A08FA76D6AC29A8890 Ref B: CO6AA3150218027 Ref C: 2024-10-29T23:43:51Z' + status: 404 Not Found + code: 404 + duration: 90.908675ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_MapsConflictBlockedAtRuntime.yaml b/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_MapsConflictBlockedAtRuntime.yaml new file mode 100644 index 00000000000..740f9945e8c --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_MapsConflictBlockedAtRuntime.yaml @@ -0,0 +1,437 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-rdwpkg","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 2d4d6074488c774735dc42a88af37b4b774021eee35ee1e75c83eb1d44183888 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg","name":"asotest-rg-rdwpkg","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: A49E144715FB41EEB341AED3EE92E1B6 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:41Z' + status: 201 Created + code: 201 + duration: 321.141303ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg","name":"asotest-rg-rdwpkg","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 2F1C1C28D6E246A3BE6D325134975A91 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:42Z' + status: 200 OK + code: 200 + duration: 37.770539ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-cxqkrf"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 108ddd2a7acbd75404ecf0a74ed18173fb2ac9a6d7bd2f63912f50eda75e1a7d + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf?api-version=2023-01-31 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf","name":"asotest-mi-cxqkrf","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"14f8f78e-b305-4ee6-85a0-d04d6581e9ee","clientId":"dc577f93-a905-4a4c-8bee-282cac94a040"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Location: + - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: F06DD150FE5D469AB434910E270F5637 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:44Z' + status: 201 Created + code: 201 + duration: 944.911763ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-cxqkrf"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 108ddd2a7acbd75404ecf0a74ed18173fb2ac9a6d7bd2f63912f50eda75e1a7d + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf?api-version=2023-01-31 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf","name":"asotest-mi-cxqkrf","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"14f8f78e-b305-4ee6-85a0-d04d6581e9ee","clientId":"dc577f93-a905-4a4c-8bee-282cac94a040"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 4EE7E52C41BD4A72847EA4822833F6F0 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:47Z' + status: 200 OK + code: 200 + duration: 278.23988ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf?api-version=2023-01-31 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf","name":"asotest-mi-cxqkrf","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"14f8f78e-b305-4ee6-85a0-d04d6581e9ee","clientId":"dc577f93-a905-4a4c-8bee-282cac94a040"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: CF7246C86B1A48B694D7B811FFE9D8AE Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:47Z' + status: 200 OK + code: 200 + duration: 67.224563ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-cxqkrf?api-version=2023-01-31 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: BF4A75CF54CF4D14A3BD1139A55D9935 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:48Z' + status: 200 OK + code: 200 + duration: 3.051442631s + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rdwpkg?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRSRFdQS0ctV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638659081185709570&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=CifGlRKX0LTsVK2SXYpr4lPv8Af_zYZTrjeXHbo_eQfSZXss4Ouz29VHBmjJKUoT6-SH1_e82wT6eVGjkrK3er2oWHrLgJqf719n9LRQCq75luTWmcxSRpZ_QUK3TDtsYLppSUNMlFXHKtdo7FisTc0l75__Vu1uRmdNDkN33f9bdVcGcUmB3q2nCU7CSPWAGDv1QG4BJTBTazlVFErwz1lw53xjOVlWgw5rnhPnpodE1dwYv8IrzhBk0lmoDis6MEgX-rq_bQcqNt-SkHmBy1be-noP1iVh-dkEL5aF1kjYayek0rjOoGvrQ7bo7GW5fbewbb3hD9vhsFFUVNoRSw&h=iC13RnrYKeaGpn3ZHsGFpcs3s7ifudc6MXGa7_q28l4 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 816DFF5FF7D14BA5BC53C65BF197D082 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:01:58Z' + status: 202 Accepted + code: 202 + duration: 226.166405ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRSRFdQS0ctV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638659081185709570&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=CifGlRKX0LTsVK2SXYpr4lPv8Af_zYZTrjeXHbo_eQfSZXss4Ouz29VHBmjJKUoT6-SH1_e82wT6eVGjkrK3er2oWHrLgJqf719n9LRQCq75luTWmcxSRpZ_QUK3TDtsYLppSUNMlFXHKtdo7FisTc0l75__Vu1uRmdNDkN33f9bdVcGcUmB3q2nCU7CSPWAGDv1QG4BJTBTazlVFErwz1lw53xjOVlWgw5rnhPnpodE1dwYv8IrzhBk0lmoDis6MEgX-rq_bQcqNt-SkHmBy1be-noP1iVh-dkEL5aF1kjYayek0rjOoGvrQ7bo7GW5fbewbb3hD9vhsFFUVNoRSw&h=iC13RnrYKeaGpn3ZHsGFpcs3s7ifudc6MXGa7_q28l4 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 773494EF27E2470BAECF5323CB4E4538 Ref B: CO6AA3150217033 Ref C: 2024-10-30T18:02:13Z' + status: 200 OK + code: 200 + duration: 27.130213ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_Rejected.yaml b/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_Rejected.yaml new file mode 100644 index 00000000000..5cd17151a8a --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConflictingConfigMaps_Rejected.yaml @@ -0,0 +1,217 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-xcezfa","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 463dfca1f4233938f8d024addf0870c2fc6c074e76c2460fabd4d7b2929e67f8 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xcezfa?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xcezfa","name":"asotest-rg-xcezfa","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 7D476705DD2649AC8CBC0324B02667CD Ref B: CO6AA3150218053 Ref C: 2024-10-21T23:51:52Z' + status: 201 Created + code: 201 + duration: 389.662252ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xcezfa?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xcezfa","name":"asotest-rg-xcezfa","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4218FFEFE0B34B76A523EE5C8D184943 Ref B: CO6AA3150218053 Ref C: 2024-10-21T23:51:53Z' + status: 200 OK + code: 200 + duration: 46.127555ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-xcezfa?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYQ0VaRkEtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651515143155703&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=obui9ZX4bT6VwiFRaU9lpLRtk4fQ10Qw-F0RO1wrZ1JzJyd485QOTHFdOup202ruD7mMFK5u4k26rmcEd0ZIIdKooOgZ0fnXI4W1P8YNmF3d_svkXKD86qf0HGxnnRSyj_YGl4ZatymYqb07QY4ohaKRXorD7G5bZ_CTP1wPosJhMKDEDm8OgclmO0Z3CAXg12_lTqth-BX0xOp7yo16uwGENMxgkgldiGlP0lvScvH8x4lEKM-V82osTCvE3Wj1-okHUVUHrWoMYVevqFZ4uoIp76kDOk8-e5Z8uUGj7HI3L291wIhMmE3zYlxRYTdW8qU1wU6OctS4fUFIz9JFcw&h=KReQ4n6fozq77XwlXIcREX1A8rB2kszcnwA4gqVf1Mw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 54DDE631CBC44F8DA5F5211123CAEA0B Ref B: CO6AA3150218053 Ref C: 2024-10-21T23:51:54Z' + status: 202 Accepted + code: 202 + duration: 300.726961ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRYQ0VaRkEtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651515143155703&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=obui9ZX4bT6VwiFRaU9lpLRtk4fQ10Qw-F0RO1wrZ1JzJyd485QOTHFdOup202ruD7mMFK5u4k26rmcEd0ZIIdKooOgZ0fnXI4W1P8YNmF3d_svkXKD86qf0HGxnnRSyj_YGl4ZatymYqb07QY4ohaKRXorD7G5bZ_CTP1wPosJhMKDEDm8OgclmO0Z3CAXg12_lTqth-BX0xOp7yo16uwGENMxgkgldiGlP0lvScvH8x4lEKM-V82osTCvE3Wj1-okHUVUHrWoMYVevqFZ4uoIp76kDOk8-e5Z8uUGj7HI3L291wIhMmE3zYlxRYTdW8qU1wU6OctS4fUFIz9JFcw&h=KReQ4n6fozq77XwlXIcREX1A8rB2kszcnwA4gqVf1Mw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: DFA39443428F481AA1B7692590BE017F Ref B: CO6AA3150218053 Ref C: 2024-10-21T23:52:09Z' + status: 200 OK + code: 200 + duration: 192.609261ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_MapsConflictBlockedAtRuntime.yaml b/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_MapsConflictBlockedAtRuntime.yaml new file mode 100644 index 00000000000..26965be7d93 --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_MapsConflictBlockedAtRuntime.yaml @@ -0,0 +1,437 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-phlndt","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - d957e60f36b22ae71fedd4a4877cc8995c45bc54f68abcaeee86302c7857d62c + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt","name":"asotest-rg-phlndt","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 501D980A78CA4A54843649F13A3BA31D Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:28Z' + status: 201 Created + code: 201 + duration: 229.564383ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt","name":"asotest-rg-phlndt","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 01488451242C446791A263AC58F193ED Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:29Z' + status: 200 OK + code: 200 + duration: 36.096675ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-gxjjjl"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 68cde84bde6526af786c3fb1340524bed0e49ef62b17d003eefd05582c1597c1 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl?api-version=2018-11-30 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl","name":"asotest-mi-gxjjjl","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"8500d841-c396-436f-b4ce-cc08e8958d89","clientId":"f3280086-f46e-4e15-8a2a-898e1e90a5e1"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Location: + - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: ABFB98B9260A41048D5D25A3869676FC Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:31Z' + status: 201 Created + code: 201 + duration: 885.822868ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 49 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-mi-gxjjjl"}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "49" + Content-Type: + - application/json + Test-Request-Hash: + - 68cde84bde6526af786c3fb1340524bed0e49ef62b17d003eefd05582c1597c1 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl?api-version=2018-11-30 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl","name":"asotest-mi-gxjjjl","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"8500d841-c396-436f-b4ce-cc08e8958d89","clientId":"f3280086-f46e-4e15-8a2a-898e1e90a5e1"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: B3B1C7A167C7490F82BF3615598A2948 Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:34Z' + status: 200 OK + code: 200 + duration: 187.838039ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl?api-version=2018-11-30 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 454 + uncompressed: false + body: '{"location":"westus2","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl","name":"asotest-mi-gxjjjl","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"00000000-0000-0000-0000-000000000000","principalId":"8500d841-c396-436f-b4ce-cc08e8958d89","clientId":"f3280086-f46e-4e15-8a2a-898e1e90a5e1"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "454" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 2AEB08BDAD624B46A2B05159709B386D Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:34Z' + status: 200 OK + code: 200 + duration: 67.675898ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mi-gxjjjl?api-version=2018-11-30 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 205313E1638045EAB2AFBA69A3A73FDF Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:35Z' + status: 200 OK + code: 200 + duration: 2.661756814s + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-phlndt?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRQSExORFQtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638659090056268828&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=qIIXaVix3SdPcw478tlvrHOhC52XM4Zc44b7-WQ26dPA6djLZCAIU_hHOculNW9YgBeeRd4_R1MB0GKok7Gt2bCzWhj9nMeR9mtvCCx7afqO2KMol-xQlUo59Khk1uGLdBurnCT6Vwb3SlRfsPkEgfzXvAezd9IZ0izxm1aWpl3o0k5siGQr4K9cpjlM_73tH-iJc4A6j_9uRVNISI99SWZhcoFA6_BayCwtaTRG5B2njm-HILMlNXY3xDxs5AhgdKTMb6QlmhbkBNOUIqz5BzSmBbRfjlVJODikNRKT_BZ_hkF3j-UhoSr6ahJvg5HmkoMOBhpGYgHxvry_HJ3qzQ&h=cooL_pudvNdrlpmaktsPTuo5Kei1oC1ysBx8I5Au0XE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 348D390234AE42CF84BE4F825AB211A4 Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:16:45Z' + status: 202 Accepted + code: 202 + duration: 136.529694ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRQSExORFQtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638659090056268828&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=qIIXaVix3SdPcw478tlvrHOhC52XM4Zc44b7-WQ26dPA6djLZCAIU_hHOculNW9YgBeeRd4_R1MB0GKok7Gt2bCzWhj9nMeR9mtvCCx7afqO2KMol-xQlUo59Khk1uGLdBurnCT6Vwb3SlRfsPkEgfzXvAezd9IZ0izxm1aWpl3o0k5siGQr4K9cpjlM_73tH-iJc4A6j_9uRVNISI99SWZhcoFA6_BayCwtaTRG5B2njm-HILMlNXY3xDxs5AhgdKTMb6QlmhbkBNOUIqz5BzSmBbRfjlVJODikNRKT_BZ_hkF3j-UhoSr6ahJvg5HmkoMOBhpGYgHxvry_HJ3qzQ&h=cooL_pudvNdrlpmaktsPTuo5Kei1oC1ysBx8I5Au0XE + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 14885B5A93854CADAA614660181945E2 Ref B: CO6AA3150219037 Ref C: 2024-10-30T18:17:00Z' + status: 200 OK + code: 200 + duration: 38.134783ms diff --git a/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_Rejected.yaml b/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_Rejected.yaml new file mode 100644 index 00000000000..51a650b24e9 --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportConflictingSecrets_Rejected.yaml @@ -0,0 +1,217 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-rxzlws","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 51e6d58aefec311943f8117964ef9495dc38cd6fd82f34e41b4c3ce89af3762f + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rxzlws?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rxzlws","name":"asotest-rg-rxzlws","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 6F0D81AAFEE1439693798F873E592B41 Ref B: CO6AA3150219011 Ref C: 2024-10-21T23:43:56Z' + status: 201 Created + code: 201 + duration: 637.205341ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rxzlws?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rxzlws","name":"asotest-rg-rxzlws","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D746D35BED464AA88B564B730DDC06B8 Ref B: CO6AA3150219011 Ref C: 2024-10-21T23:43:57Z' + status: 200 OK + code: 200 + duration: 64.566289ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-rxzlws?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRSWFpMV1MtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651510427193072&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=eT7um662ydXAoMJ0RD9iOgcszXKmtHYk3Nol0Nallkeb4UZHzj0b5jIQdFdXXLewJ2IZUiAU2bBrSzbmF3GcKRVUaByH-DlV0XLY4nKfmP0W8SNezo_0JkwF71dF1iLdE1NMvh5PYJbXQ0mzwsXLbfpwjlcyoDEXW7AA5PTmGlQEMLUSWu8WEbjxOIdNHIZ2fm3dllC_ZSIx7psutFC4kDoNxGox34agpAJ1tolnJb4wksznJIkMxpr-8JH8sRf44sWJA8_5GVgtiI7rMNk07dbqA8Qtln8acc3_RTl-vSU24QYpE_uy2IUPRTHlh8SFDTwravMtJMpXdFbZJXjM1g&h=iukf9uUFSvf6-W7KC1f1-6AG2xczdN_12S1udwbfjnU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: E9E873A57FA644F08F71885B294F99CF Ref B: CO6AA3150219011 Ref C: 2024-10-21T23:44:02Z' + status: 202 Accepted + code: 202 + duration: 311.758277ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRSWFpMV1MtV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651510427193072&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=eT7um662ydXAoMJ0RD9iOgcszXKmtHYk3Nol0Nallkeb4UZHzj0b5jIQdFdXXLewJ2IZUiAU2bBrSzbmF3GcKRVUaByH-DlV0XLY4nKfmP0W8SNezo_0JkwF71dF1iLdE1NMvh5PYJbXQ0mzwsXLbfpwjlcyoDEXW7AA5PTmGlQEMLUSWu8WEbjxOIdNHIZ2fm3dllC_ZSIx7psutFC4kDoNxGox34agpAJ1tolnJb4wksznJIkMxpr-8JH8sRf44sWJA8_5GVgtiI7rMNk07dbqA8Qtln8acc3_RTl-vSU24QYpE_uy2IUPRTHlh8SFDTwravMtJMpXdFbZJXjM1g&h=iukf9uUFSvf6-W7KC1f1-6AG2xczdN_12S1udwbfjnU + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: FB49A16168064D3ABB92806CEC7341B0 Ref B: CO6AA3150219011 Ref C: 2024-10-21T23:44:18Z' + status: 200 OK + code: 200 + duration: 52.111512ms diff --git a/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionConfigMap_Rejected.yaml b/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionConfigMap_Rejected.yaml new file mode 100644 index 00000000000..e982e4c136c --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionConfigMap_Rejected.yaml @@ -0,0 +1,217 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-bcwtao","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - f66b071c9736b1a178094c3ab03fae324f18e4ac305552d734ce1377d33afd36 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-bcwtao?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-bcwtao","name":"asotest-rg-bcwtao","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 2169FB425DFF4DFABD8E9D65E54DDB56 Ref B: CO6AA3150218017 Ref C: 2024-10-21T23:48:09Z' + status: 201 Created + code: 201 + duration: 425.631727ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-bcwtao?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-bcwtao","name":"asotest-rg-bcwtao","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 70A352BC03944155A7AD2986A879730D Ref B: CO6AA3150218017 Ref C: 2024-10-21T23:48:09Z' + status: 200 OK + code: 200 + duration: 52.447999ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-bcwtao?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRCQ1dUQU8tV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651512913980660&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=AeACj6pL4oLJBPWriuRCkVeWXJVVNYAbTNd3LRDNXAh53quZ002hZbk1wy7ODOnhHzEUNqUapOmQ9MaVziUSyh_UUjSZfIs65WYGlReqbk9F1nBHtX4_WAolrVPoH2Xf1EM1AYM99qI-yr3uFuAdvF3GLPlMmvPX8zr6XDoDHVLf-iZNUQo19pZrJVPi8LmcwOO8sCv_SsJGhftHP2MstT2tff9bBfm9b1yiLrnEDrLgoOTbxngjXnMlbQmop1GgYl3T4by5uCZ15cN7m0i1hslLUT8OaGJ99gGBUsW-2qcc0AWCTBe5nXaImvMA86Hp1KYQavuqDMUD3aN2H__TVw&h=gvzbHfQy0vGQ0BeSSMWSLeXiZftd02IHSyrqQkeSXwY + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 5852D35BC6394AFEADDE241131CC63AE Ref B: CO6AA3150218017 Ref C: 2024-10-21T23:48:10Z' + status: 202 Accepted + code: 202 + duration: 637.518935ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRCQ1dUQU8tV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651512913980660&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=AeACj6pL4oLJBPWriuRCkVeWXJVVNYAbTNd3LRDNXAh53quZ002hZbk1wy7ODOnhHzEUNqUapOmQ9MaVziUSyh_UUjSZfIs65WYGlReqbk9F1nBHtX4_WAolrVPoH2Xf1EM1AYM99qI-yr3uFuAdvF3GLPlMmvPX8zr6XDoDHVLf-iZNUQo19pZrJVPi8LmcwOO8sCv_SsJGhftHP2MstT2tff9bBfm9b1yiLrnEDrLgoOTbxngjXnMlbQmop1GgYl3T4by5uCZ15cN7m0i1hslLUT8OaGJ99gGBUsW-2qcc0AWCTBe5nXaImvMA86Hp1KYQavuqDMUD3aN2H__TVw&h=gvzbHfQy0vGQ0BeSSMWSLeXiZftd02IHSyrqQkeSXwY + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8A81172FBFE14C5694E64012FCDEA168 Ref B: CO6AA3150218017 Ref C: 2024-10-21T23:48:27Z' + status: 200 OK + code: 200 + duration: 45.879061ms diff --git a/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionSecret_Rejected.yaml b/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionSecret_Rejected.yaml new file mode 100644 index 00000000000..37fa41bdb4c --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportInvalidExpressionSecret_Rejected.yaml @@ -0,0 +1,217 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-akdeoo","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - 18543fcd9f8527aecb5106cb6642a29b585583ff0cf7ee1f6421be2ebf7e36d4 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-akdeoo?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-akdeoo","name":"asotest-rg-akdeoo","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 20F14407E040469CAA7DBA181F8D88DC Ref B: CO6AA3150220029 Ref C: 2024-10-21T23:36:41Z' + status: 201 Created + code: 201 + duration: 399.444955ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-akdeoo?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-akdeoo","name":"asotest-rg-akdeoo","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 90C820E0AECE437B93A47E6947244431 Ref B: CO6AA3150220029 Ref C: 2024-10-21T23:36:42Z' + status: 200 OK + code: 200 + duration: 47.921742ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-akdeoo?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRBS0RFT08tV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651506032005035&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=UHyib7pk9d9De4C0ke7xQOQTG5nhXTTuh-b3NLkqEJG3R25aBWAtVlA-QlvE2Xh6_hnluUN4Cd7HitGOo7NGCXKK1bdc5OaMJYVEz1VNY3jeIgG6cwXj_fniNzLADuS5pkdkLhR1G_7J82c7TaPmBgLg6rZken_aOofS9DAJALt4Xpo-J_uJZbtIj8UmwqiJLFpt5nWmTWMmAPlFMikpI2HvS0riTBnRdoV-5PKPYIt7433TtASd2zid6dm4v34OGRAhdHboWtlH6xvt17BwkMgHK6w69pIb70jAEAKai9XbcUncrZWVjC27-HoXySKSdnAb7WYVkgDrfM-xMjK90w&h=pratdaQfOnaCmQOIShACC_SE_MsYOcI-yyYasdTr9gQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 46026AE136C04937934F5DC32CCFC192 Ref B: CO6AA3150220029 Ref C: 2024-10-21T23:36:42Z' + status: 202 Accepted + code: 202 + duration: 251.001592ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRBS0RFT08tV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638651506032005035&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=UHyib7pk9d9De4C0ke7xQOQTG5nhXTTuh-b3NLkqEJG3R25aBWAtVlA-QlvE2Xh6_hnluUN4Cd7HitGOo7NGCXKK1bdc5OaMJYVEz1VNY3jeIgG6cwXj_fniNzLADuS5pkdkLhR1G_7J82c7TaPmBgLg6rZken_aOofS9DAJALt4Xpo-J_uJZbtIj8UmwqiJLFpt5nWmTWMmAPlFMikpI2HvS0riTBnRdoV-5PKPYIt7433TtASd2zid6dm4v34OGRAhdHboWtlH6xvt17BwkMgHK6w69pIb70jAEAKai9XbcUncrZWVjC27-HoXySKSdnAb7WYVkgDrfM-xMjK90w&h=pratdaQfOnaCmQOIShACC_SE_MsYOcI-yyYasdTr9gQ + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: DD9C2E7AFBC5414EA47468DE092ABBD4 Ref B: CO6AA3150220029 Ref C: 2024-10-21T23:36:58Z' + status: 200 OK + code: 200 + duration: 62.967846ms diff --git a/v2/internal/controllers/recordings/Test_CELExportSecret.yaml b/v2/internal/controllers/recordings/Test_CELExportSecret.yaml new file mode 100644 index 00000000000..c3fe694fc5a --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportSecret.yaml @@ -0,0 +1,645 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus2","name":"asotest-rg-ctjjzy","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - fbb0f58ecac37ad8d15b8aa42403e464bd104c961deb346792ecf973cb9be89f + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy","name":"asotest-rg-ctjjzy","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 097319396B1F48BF97629477D28F2ED7 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:33Z' + status: 200 OK + code: 200 + duration: 185.781843ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy","name":"asotest-rg-ctjjzy","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 10049955F5584AB8A5EBBE6732F00674 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:33Z' + status: 200 OK + code: 200 + duration: 36.053741ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 144 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"kind":"StorageV2","location":"westus2","name":"asoteststormkrdlt","properties":{"accessTier":"Hot"},"sku":{"name":"Standard_LRS"},"tags":null}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "144" + Content-Type: + - application/json + Test-Request-Hash: + - e94e03b35287548583b630ff512780d093d61270888c0f01dea1fc7d1886a5b0 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt?api-version=2023-01-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 1484 + uncompressed: false + body: '{"sku":{"name":"Standard_LRS","tier":"Standard"},"kind":"StorageV2","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt","name":"asoteststormkrdlt","type":"Microsoft.Storage/storageAccounts","location":"westus2","tags":{},"properties":{"keyCreationTime":{"key1":"2001-02-03T04:05:06Z","key2":"2001-02-03T04:05:06Z"},"allowCrossTenantReplication":false,"privateEndpointConnections":[],"minimumTlsVersion":"TLS1_2","allowBlobPublicAccess":false,"networkAcls":{"ipv6Rules":[],"bypass":"AzureServices","virtualNetworkRules":[],"ipRules":[],"defaultAction":"Allow"},"supportsHttpsTrafficOnly":true,"encryption":{"services":{"file":{"keyType":"Account","enabled":true,"lastEnabledTime":"2001-02-03T04:05:06Z"},"blob":{"keyType":"Account","enabled":true,"lastEnabledTime":"2001-02-03T04:05:06Z"}},"keySource":"Microsoft.Storage"},"accessTier":"Hot","provisioningState":"Succeeded","creationTime":"2001-02-03T04:05:06Z","primaryEndpoints":{"dfs":"https://asoteststormkrdlt.dfs.core.windows.net/","web":"https://asoteststormkrdlt.z5.web.core.windows.net/","blob":"https://asoteststormkrdlt.blob.core.windows.net/","queue":"https://asoteststormkrdlt.queue.core.windows.net/","table":"https://asoteststormkrdlt.table.core.windows.net/","file":"https://asoteststormkrdlt.file.core.windows.net/"},"primaryLocation":"westus2","statusOfPrimary":"available"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "1484" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 633628A586AE4A5287FE6E93024339FE Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:36Z' + status: 200 OK + code: 200 + duration: 430.714281ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt?api-version=2023-01-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 1484 + uncompressed: false + body: '{"sku":{"name":"Standard_LRS","tier":"Standard"},"kind":"StorageV2","id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt","name":"asoteststormkrdlt","type":"Microsoft.Storage/storageAccounts","location":"westus2","tags":{},"properties":{"keyCreationTime":{"key1":"2001-02-03T04:05:06Z","key2":"2001-02-03T04:05:06Z"},"allowCrossTenantReplication":false,"privateEndpointConnections":[],"minimumTlsVersion":"TLS1_2","allowBlobPublicAccess":false,"networkAcls":{"ipv6Rules":[],"bypass":"AzureServices","virtualNetworkRules":[],"ipRules":[],"defaultAction":"Allow"},"supportsHttpsTrafficOnly":true,"encryption":{"services":{"file":{"keyType":"Account","enabled":true,"lastEnabledTime":"2001-02-03T04:05:06Z"},"blob":{"keyType":"Account","enabled":true,"lastEnabledTime":"2001-02-03T04:05:06Z"}},"keySource":"Microsoft.Storage"},"accessTier":"Hot","provisioningState":"Succeeded","creationTime":"2001-02-03T04:05:06Z","primaryEndpoints":{"dfs":"https://asoteststormkrdlt.dfs.core.windows.net/","web":"https://asoteststormkrdlt.z5.web.core.windows.net/","blob":"https://asoteststormkrdlt.blob.core.windows.net/","queue":"https://asoteststormkrdlt.queue.core.windows.net/","table":"https://asoteststormkrdlt.table.core.windows.net/","file":"https://asoteststormkrdlt.file.core.windows.net/"},"primaryLocation":"westus2","statusOfPrimary":"available"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "1484" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8D654E631ADD4D478A5ACE4491362F99 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:36Z' + status: 200 OK + code: 200 + duration: 50.873741ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt/listKeys?api-version=2023-05-01 + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 380 + uncompressed: false + body: '{"keys":[{"creationTime":"2001-02-03T04:05:06Z","keyName":"key1","value":"{KEY}","permissions":"FULL"},{"creationTime":"2001-02-03T04:05:06Z","keyName":"key2","value":"{KEY}","permissions":"FULL"}]}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "380" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Resource-Requests: + - "11999" + X-Msedge-Ref: + - 'Ref A: E7AB9A98620B4F21A8830F196972B8CD Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:37Z' + status: 200 OK + code: 200 + duration: 277.119453ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: C7E045ED9B6043478DA4DC8DC01627B7 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:40Z' + status: 202 Accepted + code: 202 + duration: 213.76243ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348355860787&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=RfadkVjjl6yK-0iHKAAEDBl-N1I6ZC_EWU5_dYSzsT99WCdTw1WrOWh7yhShzZMq7wyVzJmEWuZq3R6oLkDMnKxb2S1h_SYVfBg2PBcDtZRrkpR2IpeDCPWZe_NmsVqr7cv45QEJHqv22JkFaSlF00oAj-D9cIx7ofRKR-Xp4Po0-ivIeWV2-67PnP66SHoCo90LQvZKcMZFDmCmFQyyNFDuwgkkPSYmimTN2CiAH5xI34GoXhipKB0xyft2MTHgwubG24iYWY6Q8xrBrMk4Ci3ToxqngxClcmV9AToZbrPRRqkc3cLPIeXA_-nUUHmYvw41AY2vYMbIR0ObRH5wHw&h=_NcX0isWVSeAagWvcNHYVIPyMk40Z1I3xqC1EYNFQ40 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: C39BC02ADD3D4A809FD2A45BA9F5FF2D Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:53:55Z' + status: 202 Accepted + code: 202 + duration: 44.066595ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348507867425&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=MnTqh3F4bI-6TfQQdve7ywwlR0PZpsp8hRk8cqZbsbkMU8I2ZdrKUcYAtSUWBClqCu_lwAYPnT0mrlT-pHKQJGL5oWxNnXhGGoTBMdPsY6vAH6cfMy76P7nwpBPyuv2wLVVhhLNrdbFfOlr_8Zmuc0b-nITmPfVZpT5E9Lw8KYPTSpKQh41HlCp_OPeCtE0zaULNaXTMVxJ_UPbiRgaPtuV8bhVwncQYrDpFhYI_MkQ0J01EZdBSGLa1CU8APdEK07oYK0VeAN7bAC2_QKj3da-tbr28Mfubmmofi9h9tydDu4AtzoNDJ2nkd6-Z8wEzj8OVsmfacxy0qJI2f2ESeQ&h=jMFt2MzXSITH0FF1I3Zqeo4zDCsmzeIwb_HnKNQFHHg + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: BC485A1201E34214BE290C35529FE654 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:54:10Z' + status: 202 Accepted + code: 202 + duration: 150.019303ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348659904053&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=zcNf2LhYnqRk3HUN-ob9PMcxMLRCA9SKJDGkjiAnb36PFKa5nqJqHflbaJKFU1y6A8Z4VTMgWvllj51AUpgsqbyDtDyBtBsvw6ZrESYfPBgUlDDRMw5tSAeY8hBlJ8E2eD5Bs9j8jaNcFOT43bqommeBw9xO3wceQ0q5Mtsqs3DSek4S9TTvJbqBnq5c2CDkJ5VXOSO8AdWyNHFoZLMoeOAqcKiyDSRIMcA9ZaJtxYE8asJQeZX-RIptAbaFicUC2aS1r3NCqwPhCLTIhCiRP4kbeGvLEefLLIq2AZuvWeM_MLKIBKRT38rr7wc1OYj1fgiWsL7ZqKuMlQUJpLCqzQ&h=8zGohpd0WAR5rJ42MNNIOYiqr959eQzFqObdk9j6Em4 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: EDE75B9BD25E41BEB34F8B000B4A763B Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:54:25Z' + status: 202 Accepted + code: 202 + duration: 52.293249ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348811011176&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=wKZKgXWcdj66Zwbr2wZ1dQwX6ng_03xF8JXPatEFJJ-4WDXuqIJGWVDHGf8dQiTtBbDTAPNaiC259Qs97GrmhOwRs6tWKjVfsIDiuDb2cuMgWffTSLADMrJ9ZbLlhYMT8b_gYjQZm5xQSCf0YDr50Piqyls6dmv-S3M6i1hNV_TmYhBMo_OAJXUyHphjQ35nLD8nDzcMAZIdtKjFW1o1rotkFVUGsoBmQFofUcbosms41_kSLqLDB5uDJH0O4fY5kALG-F8jALksMVkagb_QAP52EQJdmBOPJEwmbMt7eHzeQBznD0bvIrbBeq4wUx_dLP-rH8vzOLv4qSTc9wxGFg&h=0B9vd3jJiiu_2smnd_WCy6nxkV_jW_xOrrQyWc_0tao + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4E80AD6E431F426D84A00C870F2C9FC7 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:54:41Z' + status: 202 Accepted + code: 202 + duration: 38.536357ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDVEpKWlktV0VTVFVTMiIsImpvYkxvY2F0aW9uIjoid2VzdHVzMiJ9?api-version=2020-06-01&t=638657348202943802&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Dt26hOzFPR6i4R74igT-u_oeekaQmA2WSPhwVQv_X1SWsjoJr3MzSawo5p12orx4r10wTNn73PcNPB2WPQIfehLuSqS5Him_uEAFmzO1URR_u3h9nOXT43CAYc9MtvA1hm_PpUtGueJJkRkmURM7ds3-ktv08IrjjWIS_Tt2mlvKopgLfE-MtiSiBFXrQWBQ6-2HlrTM-52h07elFQoT_lZlriKDH1GHOPUI0ngbCwAN3-iw62YykfhtxzhUEthGQSG7HchQpgBO9j6wvUDph85xjncS5GcqKM8q-A9yFqb8VYTcfDj97Z2DrIAo8dKS67pKMtqHVpyCkvzX_vpOHQ&h=7HMkZyOn1NVTcEz4Xnylx2RTf5hR9Q8Fqxufp_ytCcc + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 82DFE9E3B32A40A2971A5F6E985154E7 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:54:56Z' + status: 200 OK + code: 200 + duration: 38.97006ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-ctjjzy/providers/Microsoft.Storage/storageAccounts/asoteststormkrdlt?api-version=2023-01-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 109 + uncompressed: false + body: '{"error":{"code":"ResourceGroupNotFound","message":"Resource group ''asotest-rg-ctjjzy'' could not be found."}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "109" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: 4F508124D4024067A27B513490A21D71 Ref B: CO6AA3150217039 Ref C: 2024-10-28T17:55:00Z' + status: 404 Not Found + code: 404 + duration: 92.411118ms diff --git a/v2/internal/controllers/recordings/Test_CELExportSecretPropertyOnDifferentVersion.yaml b/v2/internal/controllers/recordings/Test_CELExportSecretPropertyOnDifferentVersion.yaml new file mode 100644 index 00000000000..391639455bf --- /dev/null +++ b/v2/internal/controllers/recordings/Test_CELExportSecretPropertyOnDifferentVersion.yaml @@ -0,0 +1,2396 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 93 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"location":"westus3","name":"asotest-rg-cnnagh","tags":{"CreatedAt":"2001-02-03T04:05:06Z"}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "93" + Content-Type: + - application/json + Test-Request-Hash: + - effb94ae51d658414b916c94dc8270f081e692b845d01fff7c6940f87c78337e + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh?api-version=2020-06-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh","name":"asotest-rg-cnnagh","type":"Microsoft.Resources/resourceGroups","location":"westus3","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: CFEEBDE3AA624199A3183F5E906284BC Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:47:49Z' + status: 201 Created + code: 201 + duration: 296.958155ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh?api-version=2020-06-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 276 + uncompressed: false + body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh","name":"asotest-rg-cnnagh","type":"Microsoft.Resources/resourceGroups","location":"westus3","tags":{"CreatedAt":"2001-02-03T04:05:06Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "276" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D210B91E6F3443E8A91CCF10D7F5B09A Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:47:49Z' + status: 200 OK + code: 200 + duration: 51.71704ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 249 + uncompressed: false + body: '{"error":{"code":"ResourceNotFound","message":"The Resource ''Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym'' under resource group ''asotest-rg-cnnagh'' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "249" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: C114B9E609D74C9283780F4F91625F8B Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:47:52Z' + status: 404 Not Found + code: 404 + duration: 115.019258ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 429 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: '{"identity":{"type":"SystemAssigned"},"location":"westus3","name":"asotest-mc-qtrqym","properties":{"addonProfiles":null,"agentPoolProfiles":[{"availabilityZones":null,"count":1,"mode":"System","name":"ap1","nodeLabels":{},"nodeTaints":[],"osType":"Linux","tags":{},"vmSize":"Standard_DS2_v2"}],"dnsPrefix":"aso","identityProfile":null,"networkProfile":{"dockerBridgeCidr":"172.17.0.1/16"},"privateLinkResources":null},"tags":{}}' + form: {} + headers: + Accept: + - application/json + Content-Length: + - "429" + Content-Type: + - application/json + Test-Request-Hash: + - b5e3850797eee228b8645ce5118945fae01f1afe9d08d121f6ebbd25610671a8 + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym?api-version=2021-05-01 + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 1962 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym", + "location": "westus3", + "name": "asotest-mc-qtrqym", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-zqaci4ci.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-zqaci4ci.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Creating", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "tags": {}, + "nodeLabels": {}, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + } + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "2c87afc4-da93-41d0-bafa-2b6e60ccc745", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Azure-Asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + Cache-Control: + - no-cache + Content-Length: + - "1962" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Writes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 9A39FCA30D194A5DAA50DBCA522F4FB9 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:47:52Z' + status: 201 Created + code: 201 + duration: 5.900707652s + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 96A056E16D36442FB77D3301D6709B23 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:48:06Z' + status: 200 OK + code: 200 + duration: 238.370626ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: ABCD00A9477F448DA851FDFAADCA44BA Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:48:10Z' + status: 200 OK + code: 200 + duration: 254.145904ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: EB7903FB55F946AEBA57B0EE52401951 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:48:19Z' + status: 200 OK + code: 200 + duration: 180.110171ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 552B7FCD627240C5B6985F084F0358A4 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:48:35Z' + status: 200 OK + code: 200 + duration: 240.751131ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 4A27BB0F73824B708D1F5BC2DDD17F6A Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:49:07Z' + status: 200 OK + code: 200 + duration: 156.640485ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E7E85A8424784B1F96B67F3577D02E67 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:50:08Z' + status: 200 OK + code: 200 + duration: 282.899234ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 122 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "InProgress", + "startTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "122" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: CB84BCCC066241E2B1C163A1E9F5231E Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:51:08Z' + status: 200 OK + code: 200 + duration: 108.498415ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus3/operations/53762315-c3a5-45e8-893c-197023cc9c38?api-version=2016-03-30&t=638658424781639915&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=7LUMVmDeVUaA4iMkezsmCOmq20bm_brMWKzVcSEq88E9fCXb7Ub6SkPxtjfegewBXOz60CtzmQ7obD4_nBiovJN1pcrVPm8RPp29Y7SnFsKIpZopDQ23FpzTnDiJLpWTOj0KIY_BG1Uur9SWtgpP64coH0KvcAzwU-dWyU7UAwD_jPDG2o8461DrbshHxJjnUX-5vEzesZ_3DsoH7arE32-etjao_KlxX8DGTYqsyiZmVaW2fHySDFReSUt1A9XIDK3kOi00tblUgEwXLlQQ9FJjkxFHfnQxK9tXmsOcPK3WcGhkSIlo977uOHS_hrFt_rmQRVE7ZW9pExQhGhsyhA&h=OxbgbOslc1UxGqOrscf5wRXVawVezRZhJcOXQApUiQ8 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 164 + uncompressed: false + body: |- + { + "name": "53762315-c3a5-45e8-893c-197023cc9c38", + "status": "Succeeded", + "startTime": "2001-02-03T04:05:06Z", + "endTime": "2001-02-03T04:05:06Z" + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "164" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 52DFAE3031CB48F5A52D748AFFF21B87 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:09Z' + status: 200 OK + code: 200 + duration: 230.46385ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym", + "location": "westus3", + "name": "asotest-mc-qtrqym", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-zqaci4ci.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-zqaci4ci.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3/providers/Microsoft.Network/publicIPAddresses/0e5059b1-ad5f-4fd2-8011-2e60d7907715" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-qtrqym-agentpool", + "clientId": "5671ad9e-1efe-46de-848a-c936018fb4eb", + "objectId": "c9befe3a-ff5e-40df-b2e1-1f45e17e6efa" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "2c87afc4-da93-41d0-bafa-2b6e60ccc745", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: F7259577F3014FF79738BF87E14F61A0 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:09Z' + status: 200 OK + code: 200 + duration: 889.666315ms + - id: 13 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym?api-version=2021-05-01 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 2578 + uncompressed: false + body: |- + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym", + "location": "westus3", + "name": "asotest-mc-qtrqym", + "type": "Microsoft.ContainerService/ManagedClusters", + "properties": { + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "kubernetesVersion": "1.29.9", + "dnsPrefix": "aso", + "fqdn": "aso-zqaci4ci.hcp.westus3.azmk8s.io", + "azurePortalFQDN": "aso-zqaci4ci.portal.hcp.westus3.azmk8s.io", + "agentPoolProfiles": [ + { + "name": "ap1", + "count": 1, + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 128, + "osDiskType": "Managed", + "kubeletDiskType": "OS", + "maxPods": 110, + "type": "VirtualMachineScaleSets", + "provisioningState": "Succeeded", + "powerState": { + "code": "Running" + }, + "orchestratorVersion": "1.29.9", + "enableNodePublicIP": false, + "mode": "System", + "osType": "Linux", + "osSKU": "Ubuntu", + "nodeImageVersion": "AKSUbuntu-2204gen2containerd-202410.15.0", + "upgradeSettings": { + "maxSurge": "10%" + }, + "enableFIPS": false + } + ], + "servicePrincipalProfile": { + "clientId": "msi" + }, + "nodeResourceGroup": "MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3", + "enableRBAC": true, + "networkProfile": { + "networkPlugin": "kubenet", + "loadBalancerSku": "standard", + "loadBalancerProfile": { + "managedOutboundIPs": { + "count": 1 + }, + "effectiveOutboundIPs": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3/providers/Microsoft.Network/publicIPAddresses/0e5059b1-ad5f-4fd2-8011-2e60d7907715" + } + ] + }, + "podCidr": "10.244.0.0/16", + "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", + "dockerBridgeCidr": "172.17.0.1/16", + "outboundType": "loadBalancer" + }, + "maxAgentPools": 100, + "identityProfile": { + "kubeletidentity": { + "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_asotest-rg-cnnagh_asotest-mc-qtrqym_westus3/providers/Microsoft.ManagedIdentity/userAssignedIdentities/asotest-mc-qtrqym-agentpool", + "clientId": "5671ad9e-1efe-46de-848a-c936018fb4eb", + "objectId": "c9befe3a-ff5e-40df-b2e1-1f45e17e6efa" + } + }, + "autoUpgradeProfile": {} + }, + "identity": { + "type": "SystemAssigned", + "principalId": "2c87afc4-da93-41d0-bafa-2b6e60ccc745", + "tenantId": "00000000-0000-0000-0000-000000000000" + }, + "sku": { + "name": "Basic", + "tier": "Free" + } + } + headers: + Cache-Control: + - no-cache + Content-Length: + - "2578" + Content-Type: + - application/json + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 58F06C6610A948DEA2923695B403F737 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:11Z' + status: 200 OK + code: 200 + duration: 720.077962ms + - id: 14 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh?api-version=2020-06-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Deletes: + - "11999" + X-Msedge-Ref: + - 'Ref A: 883B5E0866E8482E9D496845C35A68E1 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:16Z' + status: 202 Accepted + code: 202 + duration: 520.850452ms + - id: 15 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427526665168&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=P7oxwlPW_DNjP6r_NLWCX0eOHoEEH7Rg_5SmQBqNWRmoNSkpH37B0Df-EZ86VgMCGwtBhyHlxcyu0REqXPBtdHO7Ykn6uWR6-gi4PDwewwlIkQQnJJfGPZk0RkHMY0_wofaG9OT-Twhkca_kCJCMW3ThBkTDv1INkdkCFSm4tu5bEcOM8_kI1czhpOXdHCxmKLZ8j5_hGVaCbSPTCQH68IN56UboQ4jRUv276g9F_1_AlhzRwMZHhjWHkOL-wpKDOYJX32vY9qet2-5WByMGVvvdq7S6HytXpBuwcdVTctnwKkklNlq8P-MNL0Gn_aYroIAh9ofwcZy50wGlcTA2rg&h=W4s4MHwyOKW809F_fUHUK2QJXIWw2cGxH8UYmuLV3as + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: F01E5DB771624B47A8FA5C15466BDE89 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:32Z' + status: 202 Accepted + code: 202 + duration: 270.057065ms + - id: 16 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "1" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427681771027&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=aAhRNRflhaisMUwND1-Nci1jW-fpcxsmfbRe-n-Atu3DgTRbzPEONdLHpXEpXfio9D7aEsQsbOUpRwEQwSpPxCaAeqghy2RyRF-WbDse-kAY6lC1Bk9pvRbDCl75Kx6P-O8oYr-71gxe9f6ROMDQkL7bcIp0zeM1k3IjyWaX2QLR6-6M0v7IBcky0xlBJ8hz9Udx9IKR94eBIg0MfiGGH6cDchYLtWb7kt0UfOaTWGhj7H9VQ0nK1IjGEblIe9nkVcg2t4jTjEkrzhfxiwlfubwzLhMLbNi1c9z8euzwSYvDQPGE4QKp55N9uGB8LIAFSpisBfr74DXdvlq7evd6Rw&h=6G9KZIRQj-8A177CVG8e8sCQEjvlQDIUxFhw140MN4M + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 45F4D09DB9F04E4FB00831B00A71BCA5 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:52:47Z' + status: 202 Accepted + code: 202 + duration: 237.177437ms + - id: 17 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "2" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427837076870&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=UYaoNxbuxXT6et0wfN19L6S9k48fdrO_soMZEtYK43q1trrt-DTn7l-zQhKbVGYskIOPKqXlxiyTAdEESzIoeb0Un8BybiEGrxRukBRwrLqG7v0hy-KKhQdgrm1MGnVZXMW4PGAkORt4_wc5JqYTocxAvRJSpvWY_EyTkBfZrd-6N0DcsOkeRP11PADVV8Mwslf2JyA1D1rYdcG6EW0VmgWtcsDJnCX7K6bDzHB1CZTg3JriSMH8xY4vmDuS4ppGogF3fal2FaHlnSGypFYFyLIbzv9tYfY5KSci-q2yib_cOfuCO74D8uUeBdGw22P_rq6sVnhdEtUDxV6RxGv8sA&h=F9v8lo8sag7DoXHQ9dL_bSFVF_cu4vW3zjAMWIRiyqs + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 736B66A5711C4A0ABFDECA5382B29565 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:53:03Z' + status: 202 Accepted + code: 202 + duration: 279.245396ms + - id: 18 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "3" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427991511370&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=xYQCTdTBpqEBMP_zR23XF3jbPfGWFANzuBoqanEcxL83kX9kBsVu2usaoU3ilZJfKl761eFnL7RUKJ5Yq1hWFsik6parwlGfg0kcP15jeXTrDhL6esbSBePX8KJbeQ8NMRfSrQn9zgMRfMol9PHSKKWq6R8pANXsL5aIexSCM-jf02aIarXoll2qFMfP2g0WxUdErhNUxprTGyJDo1ifZmvAzPq7QmCug5suz9bMXZ8KB5BjG_QOnpRa3Mqpori6bZoVQF51uTY4BK_suZJLEssLTUCdvLc6PCXc0lFpVwEk2bYJNGRDoZshBnV4qOobdz1Cr5gO_sqza_hnw1PKoQ&h=bXLjB52zyI1Q1FAdUKqesGKUffGETquA-db5soGbSNk + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 211DCF0859E0435092817472C4BA4137 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:53:19Z' + status: 202 Accepted + code: 202 + duration: 158.643342ms + - id: 19 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "4" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428145861441&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=djx9Ua1xIGxIw5TjjaqM8eacgsrR_tTSvvNy_hShU7VIvpagijlZ7v6yIVxAGRhdN_6bzv0fKABP_5MUVGgy3tmb-G3em1AGZfcWFwJWF1aRxLqiy8NI3Y871iZZlcisQb2L8odJ8xrm_spNPThCr54zs-xoAJGDKo5jDe6L1zd7ZoM6hs8bYc5yyxUFyeRpfQaKr2WHEwwqOlCK3aiSLgmmJgCE3fmscMz_JQ310rpu4nJlzHLBfIQLmeP_FmNZs10B5Z_uRxiLwOuyOzHvivD851pkTfYLw0p4e7PvHinzUyOzqWZQgbFxdjXfVLn_-1SwJ1_nW67nGYPVsGiq5g&h=fAtZC-SlvPNGNmO_x4DGkJ-qaWn8IkRc8_vzAmcXoJE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: F38C3C5417F44ED38D6270059329910C Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:53:34Z' + status: 202 Accepted + code: 202 + duration: 273.980026ms + - id: 20 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "5" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428301203523&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=SvwLcY7z0QZxLq448GdVeQaeHtW-45EDhNdLxLbHfrYXo1r133v9D4wJoDvqYrG0x9p6CP2iyFfRRoIDcrHwLA17g1qTBG4ZgHMXwm6WdyX4p0zHhcKTL8kt9zVh3fcFvdk_2rRjUPlPqTVa_7EuzcUXaxvs2_yLDySAEoquKK-4DQAjcguZojWofSFbr6mQ3U1dXdOtlAaR2iKGja-WfTTiDcuUQrWQxP1AJJEJoNEbzNomMEAc6ad0c9B9hbLEQbN35Vgput0r44P6HPttIQgcRbCSNnf65zYOMKgmh0Ir2y-LTXZtcU7XFVF_ArCuTIemBWJ32B3S6ng8nq2V3A&h=iwu8k9z3WQd8RYTDx_HGMA3b8YHeiZxBx65_dMTJJas + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 166FDD1E3D6E4C9C87D71622094FB710 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:53:49Z' + status: 202 Accepted + code: 202 + duration: 245.561188ms + - id: 21 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "6" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428456713018&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=fI_wgKNdSDKkujr2yU7_obFw-IX5La7mMxAIASBNYOCO3bfHuajPXc9IUfs4Lsd4f3-4La55nPeqHuFqURhARXlEwQxX6wCnYIcrDjN15xTMAE13GeMGuqhqG7D0tKqkza6IlWGP3MSg-pR6BK1rdwWXzWE-6-tVcEjnzdR0jMisPF-eS1KehfCCOrzpPT4EkYXCFi_se5hxyRZqzANR5TqrYWJzi1JtznUtyo2_TLXfw6OkY2YoS6zbOEjL0zXsKgfCzC8HzmVb1bT_ucOmJiEl97HWmHNVXTkZcuN9-4CwyWZrcSwhAXB2IkZJvKuSJkphqeQlTifJ0P854TaaJQ&h=WdRNCVAgNEC7D6p14HBWvYtiTuX5mioYBViApxhYIIE + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 53E58F8D21824DBD8CAF0D8CE8C0D2BA Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:54:05Z' + status: 202 Accepted + code: 202 + duration: 298.51147ms + - id: 22 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "7" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428612217679&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=NNWzvFhxhMK_BMDY4SUr-gZUeZEpim3xgnA81pqnLHC0E2tBxfBDe9Gxe7Hykrr-bljNKEVsiYFHj1mhri72WIla13cabgM1SQkV3x6aSuWRn6vGuS1_7K6AEcfgN8wqXgbmZ0HhPtznkilTJiYmpHhmkRtLkofQbg1aYI3OYDZNFX9KrmBFgbgDrDPoocGHvvN47vo-80Qr-XExqeRRa4ut-qH8GDIkV7qLb-6RZjCu4CJM8vaNyXvU24O86S-eJoKV8ViHAg2bxmJT45ykq7HoAtzd5IE5UG130pWivjolY6k-YlktEKHeCcEuDhPpS6rq5LvgkOOqXLimdYm1UA&h=4mMfvIX_A7aOe66WBf8CjwsfZeBHt6D0s4CRgcwmE3g + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E654954063B24199B9626EE512F028E4 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:54:20Z' + status: 202 Accepted + code: 202 + duration: 246.880926ms + - id: 23 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "8" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428767227369&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=X2n5-gkb3Fnx2RJXBOjTOsrKQ8C1J8g1lRX3jyLsOuzittzc_Mmi4pbSt0RUBaGLclxTP8tfeo31k59qEn0SP31mJmUkKLuQCWo4v1LGH_nMGeM7OuH8EOxPhOSHyjmYfo0oliQEm2M1UGRGnruRittx19W5QKPpUivHHFO70Ue_Oq2OEK5-zTrEwmNsBgVHC3FolbRJvng0MUKdgLJ1Wof1__n6TVz3xTDVCjrvtQWUv7LYTK9RSKr8L_HVQ9kLlZCLkdcQFm3ECjkvqK87Wzjyp3A6zgSMceMkRm73q6BmM3mD52S1Nn0FtoBDd1GevHZCiXuLmFoS5lYXGiF2yQ&h=b9tHHMprpMfFTSdSkZjj4b3KVk9I7foFy_SwbW_AohY + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: C9E6D27014A54314BB0D85EA702F7C6C Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:54:36Z' + status: 202 Accepted + code: 202 + duration: 250.648139ms + - id: 24 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "9" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658428922291877&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=ulV4txK-1spxapQzH4JE5gzN0jMIeNc_adYuJCZrkYD_B-0t3VerXHd6ST2c1Lb8O9DLGTIjBLCeCRWYOu1ijxRKJSPnhrH5x30ocKieOgEGdGnuEb2nvf2gI2QOYGgVDnixvK4z0wnBA72c-GEQ8tH68Ly2ol7nXHsCn1h2LUOQxHoswk8McDF7M6BEFeEoq1uLsGp5XVTcV-FcLzz8-D8XZ_I0MkY0SOhlZGePeEUkZvAoh06DWRvlFpB93g66OywVRAw7e9yRrmQgEg-R98xyupHrG34prO-OzF9y3xkfYR-FtsqOU5t1z_MpKE8Xtf2XBA5lIhDmUglW0Msyrw&h=1-c8UA3hTKSmtduzl6I5QDYVM9QG95vwvn0MtGtMfQw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 30F0814685AA4F37B909609F09D15841 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:54:52Z' + status: 202 Accepted + code: 202 + duration: 254.456952ms + - id: 25 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "10" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429077829082&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=Zq8TYUErVCLVZLSV794_g43wVMeAXGhQGHoB27oubeyIwaRZFs4H4-_VMgS7kHmDVxE_M4VCYqY0GEscN8Dsq6mD8DdpqnMSUVgvsEih0MTx0UJ6tUdcrLhklr9feKARfADhRhLPiykFKwpUjDivyXdzO7Sjq6MfaLJIie83BKznrYWBvitv94Pk9bqM2MvWBUZYlXHbcX3Q1WPc7azSQ6ydeSbD9E0vg7jfHiFcQC33diBEndaX3CxZSqkww6IXkNyz4_qfRuxBKsIacnZaZCM8PWU14aS_EXtUdeyxb8xcsX3mkIz3uCw6FclOs2aRO-d6ulOeU3E_2lstxfUYEA&h=GEDTE_kCK2hfJ-JXhBh99I73d3YNJIuyCS-V5lnw-Ig + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D81039E3DA4647C0950F60DE2BDBA5A4 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:55:07Z' + status: 202 Accepted + code: 202 + duration: 284.397406ms + - id: 26 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "11" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429231768420&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=oZU5cAyaPmGJ5Pl_g25apLGtm0IWATUJZrSFQ9M1y3T_nU35UHoMvIIbbMP57ROYV4b0acZizolJz95NVNOLWxsH6L-w6c86iThKwwl5VgkgI6ln1LEDxuclUIRfmIE8V5RX6NAZYHM-VzGSACkrgh2Ei8YoxVwzGey449hHNodvLkMewjqTskSKehIbXyP0Sne0kux6Gs050t76Bfy3YWAq-rjNxeiXQPPX0w08R5i_zs6b1hN_siUVeYDkHueLI8wPhodxnFGEpQa1ZqoBxK6NjjPOIOKEYdIny8Htk2MtbkzOXhh-FOV1bpoctfwdpA2LngnKZePJ75FJMlwlkw&h=kvp_TGOgoiz3Iy7jcrDqydkY_kAP__F50tTKyoXtvB8 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 825655F72BE5431C9DA89788F6740452 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:55:23Z' + status: 202 Accepted + code: 202 + duration: 102.43502ms + - id: 27 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "12" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429386381923&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=mOQCYxzZx11HIUCDYvNIPsGTIrXfFnrgGFU9H5A8TjoPh3Ks2f1EZjH8Yzn-XnllglxFKToBVhp4Z2LUSkVPesYZM_9ifcMCNmQNIBLUVtd_WOdXr3TsE2Nkrb6UV0GdeEGfN9qZp9aRoAPAtI133HaMjlOE2VkF2qcLqApK2bRYfHAUHdGXoWBHTqcYA_oAKLSXeUTw7oKISOKixM8uVFN6OgTVbr2mO-K92ga8PfYDlbaMaXuxe4Z6Au07Xo-OCeq5qNVWhVAD1EmGHEWKI43W6mRUIqZp3ksBY1-uOm8QW4EJwzofJQwBa3FlBCcw39Qd872mcyqMZIJes_2uzw&h=4BI-FPNN4eMTU-9JmYczAJ0EE3DydLvtloXQfB2NG78 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 0AA6BE9FB728411095251B47CAFA7ADE Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:55:38Z' + status: 202 Accepted + code: 202 + duration: 354.170318ms + - id: 28 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "13" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429542570548&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=cg8jSEFQ-VzSpnoo8--2MymP-HneOpO3wPBJWALV6rt43BO2xQBUqYdCYyzVdU6jyTrRBx581YMwGMJ_iTpBfDbih_axntwPaPfZ6COtVEhOP58P39HwnzkK7E0uUTSPrIexBixdRh3AEXNTnjDzWL4kSAv3keDCq3zFd1zjXPAWlV1KaROpYquOergOuSs7ONPKxzZEVRmEH8eQ-JlZXvW-sFLyMxYtaECy5AMDliNU0Yol0afSE2qIYvOIVObguzVb_3dhVWqwARKbU3Alp29mLfws2zwM5FOl2nyKHE8a6WMgxFzwxJaapg_Bvnr04vm8O-IXjrNM0lSBzpqm0Q&h=n_CUymMBjuvAX_2vpVH5z6f0jxEqbTjCFZa5TwEmp9Q + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 0428C837335B466BB276C44475A5965B Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:55:54Z' + status: 202 Accepted + code: 202 + duration: 250.421961ms + - id: 29 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "14" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429697580667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=CLPeesp_ZZWlgtYImIVVUXXogZiTGEmrQQAdVlKtZprvQudMa9mkYmrUqe02kflmNkCTBir5mhxw4qavhYfmDq8O7kxgS92vfM1pxfUeAUp36GGiwWX0-5u7ZG_GYCJ73EHdXeFm23kYiNhyUEpQIXktHgkJ4Rd23U4kKmnE54AYRlJ7lY2HjY7tkxtWxY6qDnVPNHpybeZ0_xnMs0BOBlJk06pj-MdjzDvUxBXyl2TP-WEbnmhUSL5U2T8rBZ22exeMHxEyUaDqt0bGandjMnYJTNjluy3EVJlHI6Hmgt18gOzOKLEI35popMWXtrdbx1h1UAFTndLi1lw7xEAgPw&h=dhBwUjC1aVbZsuBfVvd4NF-aP5r4j0KdQiw9vdoiuAA + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 34064A139D5E4FCABF9E3BACDE1F8256 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:56:09Z' + status: 202 Accepted + code: 202 + duration: 249.663021ms + - id: 30 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "15" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658429853161941&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=k7jh5WH3RCnRiffNNkgwcx5En8PKFQ17vdnPPNXEEZTNHzlifc726DVM-k-bkOgmR1MSOnKnLxZy9vy1nf0ztDpp7RhgP4DTX1gJ15aFB8uO3K-hSN-SlgVJ6BOfn2KfHW0XnB3Z8JcFI2BBSftQEAaPPf8zES6-xlAzI4OMScooqtFUTZPC526SV3Bp1sC1NwoAt-VNt3wUaVgXV2nGf33tMvzKnOFYNHPabpZp7P6p9T4fdF8QXEv6DgdKJ20MBBqgVqc9s0_zSSvBFY-N5aZ0U6K-dupT5NdzHXOKjkDf_yCh1e0ZD0vAs6m6MVh6zIRhhlvaNdG0XZsg4JlWPQ&h=O3qn20q2-2ifCqmuvQQ5aD9tog53ZW0BKmURy5PKkew + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 8833A1A016DE4440AF369686B84B069B Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:56:25Z' + status: 202 Accepted + code: 202 + duration: 293.598332ms + - id: 31 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "16" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430007664752&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=QVB4zV_dYKTsd9pTyo_GyK42ULsI5bQwFqmFPwmZ1txnAl2okkpYXaaw0-9kZOynp6f8iUTyOAeZez6rlQ1PVH_SV8tZcVkI0UA7X8SuXJPkcLb698wEFUA15K7YrC9cc_wGbwrANoFSjOwdR5Hu33JqCbfxfyS2gWsJH5JsHhSGUJP3rbtAfC8zl5H4Y73r3qjX1vDdUNw1_Yv3qwr81kGECfolmv7sloKVgT7PkkmVC5xMHWDMxUd4GuXhOmeAFbyudR9Qxx0V13GFPr51XC4t23mJRr9GExNPg9WzQ0n5d0eAPDXmlceadExir_hwierExntl9SEu9ukUOxt5ug&h=r00NUWURJiW1Fip84uX44vmXGMsABFGJ29-w2euNuPU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 1614FB6B8D994442BA301B73D6D740AF Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:56:40Z' + status: 202 Accepted + code: 202 + duration: 151.920862ms + - id: 32 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "17" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430161946544&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=sBSGxBZnG-1mvaSM6gMHxqOj1UBY1fjyb3lRw5HrLyExeGRNeIjmWkhcmGOX7Q1qmRDpVIUFMMSLiXfyPaHuyJFvUYLfrNncCvRd1Be4wQet-9pGmwSzhy9wCEKQ0th2CR9x1tJL2XyUBpbQiXHc1oiQHGWK5UhRvyE0beJ93KdUJzS3izBz3B-055ikbtJfQejtojroA4erZhOecECW7W318cbvF6-oqvgtwhQ6uNC5iwehL_ilBQycFjXoRkqncKzsPaYupkDYtEs0vA8Uggm3sG9LgsTppl9917qPRPbbrFUpAtOVQy9CGr7xqsM9qZ9O5n7INqmJpngjMPtMMg&h=TI_7zDmK1o5qd6iPdhOoEimJWfd4rUO2ZC6xVRqfm3w + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: D0353814843E496C9EE2C485F8E0EE0A Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:56:55Z' + status: 202 Accepted + code: 202 + duration: 275.100739ms + - id: 33 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "18" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430317465855&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=G88gD5dP8_uH4yXK3Ya8-gut9hfpAnUss5w-Z1pz9a2b_BCoeSYJfSVS_pfEIOnemEiZr6E_QdlfglPGKo2AqoDU8FO34keVhexqRFqNSUk62vR4IXL3ODmbX530n-KawWebVjNykMM5GcOkq02fA0Vg3_ROPKwCDjMIoCC5FLlOvMfTooBZuDPCzHnyRyk_CXlrkpLBBvT2_ifmqwIwUeBhuXYdU6DRx3ptlSNXo0HULWePDttjTKrc6mXcEtaVUaBHh0eVU6IyMI03LjTAcPuhL4lr4egd8VHIsvEEpDA0nzZ23wRMBReJsM_s5J601j5yvMnMW_KccvrP4qHC4g&h=XqEQ_EH_Fw76MLRxibpZWMRvzb7Xfn3c3XsnBKP0QDQ + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 0B0794CC80554EFD9D490B6B67AD232A Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:57:11Z' + status: 202 Accepted + code: 202 + duration: 269.293739ms + - id: 34 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "19" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430473061303&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=uoxWJJd4O-waia9NZemmAIv-7fO-9Hj5lM9vTQS1AkrVjp4g7uRpX6sZPHluZ409rY4MBu1NrKf6uIPIGQqpt_DQQGHicqlFVGzOFGeAxoramiQzm7huJxCbx0Smr1UYUKeNjQHaPyh-dcIx7dw5mPS8J-K2SGOtobWmAQWF34vCagC8Fydev1jC4Y7QD8a14PT4RcpdnY-Z5s8cYeOVFxAeVfTg4FjZkShLpnrSMCVFPd7MpfgKAfVcT3v7u0zeuk5EHo0aCCbgTgxpnGfXwsHpYspQh7sbDUYb45LYtrjN5_V6VOtTR4KeoyhpQZb4L9fF_kCh1Yh9pkrgZe33Pg&h=ZGW8D3ayslzD6U315wcKAFKbsBS1SyubDQso3ENzRBk + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 5B176123678740FDB55BD68B4208927C Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:57:27Z' + status: 202 Accepted + code: 202 + duration: 277.211304ms + - id: 35 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "20" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430628548149&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=LUdVAmOGlUqPSqVAW6ydPvw2C87OZBLSo7Ph8qJoXc4LG4iGebHVqD1FnUaIGgTzDulk36L1SPJHvcnbKyDhnwTzOFUOIMw8L6sbjsOiuqQFyZThKyu9K27i-zHqZdcw12e0bAFdmjWwFtG_yJSDTX294X3Rao7PFPAbGfcSV-KTZskQoamxUklkx7LEzptwGqBYotLvRVBJtPdofZq3rz5AwjinrxBwiNajAKkAD5nSCkL_x0Lv5Hk-Usx285aDrtW9iYtsEJmOVTNPSSEJRKunVO-nklKXMJnsNYKb796bCOidXA0Z_qNWN_-bV73GfO5dSJ1lbKbJ6-2GDK9KgA&h=nVOE9vhr0dRKgcGd9JNYrF5MlcT_nE53prVAj8YUlgU + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 540630F629ED4F54A86581F3D1B47032 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:57:42Z' + status: 202 Accepted + code: 202 + duration: 265.661239ms + - id: 36 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "21" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430783944500&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=J5zZuYbMGMZ-gWVQHvNrMLI1Rx67VhhONn5meY5_Z_3xHp3VAduAb3xcy2yQ9NIRqR0VHJRoTLec7BdJRXjaEZoC3sWk7WHpfwGfQIjvrwLkX0qQWbUwOcm1fL5-hSXgWpu5ViKm60KgWCR8XOisv8s0hhwBB0s6XoHejwqpQo8WP9O6tVsccwohgoZdQ9nApehHkYpu7QgkdnNS0CG4IlOhRfAEWXqG9md_4pozpqeZHwyCLqpeQZY3wR7KAVSrZwgrzSybi7z2g8Oa_wo966Y5BifvNAw3ZvFJbmNRE4VylqI0b6yXt4YWZcwk_T-2pmpcFwrSnY8watjcT-BGBg&h=NsHpZ5843Pb02J8iPNmqIOwz3W_HuF5EwshnFMVCF04 + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: 36322D1BAB5E4EA8B6EE25450AEF2A7C Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:57:58Z' + status: 202 Accepted + code: 202 + duration: 263.634687ms + - id: 37 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "22" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658430939190213&c=MIIHhzCCBm-gAwIBAgITHgVxvH65_BmPrKxDIgAABXG8fjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSW5mcmEgQ0EgMDYwHhcNMjQwOTI1MTkzNzA4WhcNMjUwMzI0MTkzNzA4WjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKlHcl7gn1b6aLS1hLftgvWE8n-Z9liLRsNGgjYfyY_1N6TVDEHJTtctREIaCRDPEC-hePKBe7OS45JIAD6cl5AGU_dQlGd-3bBZeVfAPJFUnC910pwhDca2OXlf4LyB1KSofXaA4xDB6G7cHXRld_URCnol2LHQEGox0vBzaPz30AUB0ZhAatZgqhXy5qnroV3zbEZC3m4qLDSnG8QNEnw8Wv5GpYH_MxK9mgDPwoIObeDBnjtQonKzvItZ8jXwF-wEmcVAnhr6Dvq3rWdBY9616kXvQ7E3eEvGqMn9W_NZTAqlaanfaACfITkIJZkgsSoJGw5USCMC-vzAb1Ms0j0CAwEAAaOCBHQwggRwMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFghfmRS4WsmTQCAWQCAQcwggHLBggrBgEFBQcBAQSCAb0wggG5MGMGCCsGAQUFBzAChldodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MFMGCCsGAQUFBzAChkdodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CTDJQS0lJTlRDQTAyLkFNRS5HQkxfQU1FJTIwSW5mcmElMjBDQSUyMDA2LmNydDBTBggrBgEFBQcwAoZHaHR0cDovL2NybDMuYW1lLmdibC9haWEvQkwyUEtJSU5UQ0EwMi5BTUUuR0JMX0FNRSUyMEluZnJhJTIwQ0ElMjAwNi5jcnQwUwYIKwYBBQUHMAKGR2h0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JMMlBLSUlOVENBMDIuQU1FLkdCTF9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3J0MB0GA1UdDgQWBBTELag1gS_F07Xj1us9l4ySYrHYYjAOBgNVHQ8BAf8EBAMCBaAwggEmBgNVHR8EggEdMIIBGTCCARWgggERoIIBDYY_aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JshjFodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJbmZyYSUyMENBJTIwMDYuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEAjAfBgNVHSMEGDAWgBTxRmjG8cPwKy19i2rhsvm-NfzRQTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABJx3Gb3LtjBZ4x70SioNIk8ap3qwt2DMEu9dXEhi28jFB87BBsTCkNeuhGlLzHm7Ykx6xpUjJp4F2_qmJKrQjDH4U0VYT_yc8Ow5mxrFJcewgTXzwmwqXOodok5WWOUVP4Mmdp_O_3je1dVgw4TrdrypIZImBn2jVDrXQ79fFXTR-Td0XMOtWPDwreoMRagD769QW4hlGtVaZCqOAzyomfSc8PhDzKhllbZQrmP-UgiLU14SDsxwq6AHG413ClcJIDGfEsEKwlUyIIAKHDwSdbO41Zs7ZQG5k_eBlGTkr-5Zye8vT7OeGf1_mGZSme6otyTUL_3-6gJ282qCPXoflc&s=BSiF-73DQicQDuqCpiXk9S-54uwS4dUn60JDEj5luIUsRpHMn9K9NDFpOxs8j0n22ORFgPp0Ol_eXurbYtqfqi6DgXMizyaFP0PuZwP8vTv3iD8YKzVoEFELlbD0T0LM7nyMaKcMQvk4NzxKSkF3CCM_nN_9wshTx5ibfgAWxaY0xSCIf2N0sV5N73SpBdr_Xc60bus3gY_seg8afYpjLun6aij-JottC__jLnXGhgpUNZV2sJUbE1CUNvpBBFUJEUN3yN3wuwMikRueQxAwztJX1pwc3R_yBwroNFCbglrWU7RoLCN9Zq-kSDgdQ26_wSGTBeSHkdaZHiNGjaiGww&h=fmaKV5P2Rsrzcll5eB2E1jEsj6Ig6D8X72T1P15S4Nw + Pragma: + - no-cache + Retry-After: + - "15" + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: E27D7B1EDA1748D9924D54F7BFADC767 Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:58:13Z' + status: 202 Accepted + code: 202 + duration: 256.998685ms + - id: 38 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Test-Request-Attempt: + - "23" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BU09URVNUOjJEUkc6MkRDTk5BR0gtV0VTVFVTMyIsImpvYkxvY2F0aW9uIjoid2VzdHVzMyJ9?api-version=2020-06-01&t=638658427368423667&c=MIIHpTCCBo2gAwIBAgITOgM6dTLGpzYZpvPtgQAEAzp1MjANBgkqhkiG9w0BAQsFADBEMRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRgwFgYDVQQDEw9BTUUgSU5GUkEgQ0EgMDEwHhcNMjQwNjI2MDEzMjIxWhcNMjUwNjIxMDEzMjIxWjBAMT4wPAYDVQQDEzVhc3luY29wZXJhdGlvbnNpZ25pbmdjZXJ0aWZpY2F0ZS5tYW5hZ2VtZW50LmF6dXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPPPKY5bDN03KptFFhiyLIyn86BlrXYFIZWYXA-hY7_WbLyWN0IxcLIUBW_I-9u-YsXOHk9WPMlUYHIFPgHW7A3FsSGfl9dd6YGapKoSSw0NkTpNXM58R54BBgLp7AhiWzK15D9T-XELNSU4Wq9sEeA5T24kazcgS2MUkzELH0I9dwu7g0dwJIuIJkoJjEzg1b1Q3Ie5HKHHNbjottJn7Q5LBS-9QtQyruuwaNTgSJpCoi4PBKVIOTBYL_Nv1wecmKmfWcT0mnhQE9zjhJTbcoN9hKSvAMqsDHtxWUFZosiw3JKIY0zb59CrVGSuOhfN3qaarwN9EAlXLqc4ZyKpsTkCAwEAAaOCBJIwggSOMCcGCSsGAQQBgjcVCgQaMBgwCgYIKwYBBQUHAwEwCgYIKwYBBQUHAwIwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUIhpDjDYTVtHiE8Ys-hZvdFs6dEoFggvX2K4Py0SACAWQCAQowggHaBggrBgEFBQcBAQSCAcwwggHIMGYGCCsGAQUFBzAChlpodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MFYGCCsGAQUFBzAChkpodHRwOi8vY3JsMi5hbWUuZ2JsL2FpYS9CWTJQS0lJTlRDQTAxLkFNRS5HQkxfQU1FJTIwSU5GUkElMjBDQSUyMDAxKDQpLmNydDBWBggrBgEFBQcwAoZKaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJSU5UQ0EwMS5BTUUuR0JMX0FNRSUyMElORlJBJTIwQ0ElMjAwMSg0KS5jcnQwVgYIKwYBBQUHMAKGSmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUlOVENBMDEuQU1FLkdCTF9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3J0MB0GA1UdDgQWBBRk_38CqdKjPVylWUR4uuqhbFGeHTAOBgNVHQ8BAf8EBAMCBaAwggE1BgNVHR8EggEsMIIBKDCCASSgggEgoIIBHIZCaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JshjRodHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBJTkZSQSUyMENBJTIwMDEoNCkuY3JsMIGdBgNVHSAEgZUwgZIwDAYKKwYBBAGCN3sBATBmBgorBgEEAYI3ewICMFgwVgYIKwYBBQUHAgIwSh5IADMAMwBlADAAMQA5ADIAMQAtADQAZAA2ADQALQA0AGYAOABjAC0AYQAwADUANQAtADUAYgBkAGEAZgBmAGQANQBlADMAMwBkMAwGCisGAQQBgjd7AwEwDAYKKwYBBAGCN3sEATAfBgNVHSMEGDAWgBTl2Ztn_PjsurvwwKidileIud8-YzAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAFsx7FtYAzSo98T5ydNFa0ukjPZ6XCQc9zo7ldqy235P_zJAUkaNgCU4EGOzbZJDoMa8mAfhyukL_0GfPeApUaY2e44ZOzoYAkeEuDiwcs-9zoQ1fCyXhn0pCumGFXRilX9KjAPaYTzDvQMEllTy_ZViwTahuKaGtFVamZguBPdaeYC_0oybtTVNQCs8hGnffhNZOMASB-5pFs35MNxsDWTVIQksDee419jqpsbWLkh6rnanILO1O_ihwb-WpvRQByQ5NGpG1-z0MQ6nRpr9wWxUi-DsrVsD38NTMIPc2uei4Ivf6qnGRvOOj0fmsciWuTTEXMaD-5a81mGlzhZc09Q&s=L5jgahV-SIHPGng5X-T6Uz9ltV0vs9005n0Ryaa0_acigAdirBAFXFIMUoeFZ8DagleegL3HEdfi4lgeGkgmf9mFNr2QJjmBSaIwNV2v5FE3NpumTp4We2gcrLGCkBurX9PFOt1VdIWgPFYV-fIJWpURkgzFCFt3pVXxEtvhaC63KvyS_8kPIYHw_yDioStLgpKaW9o5eQyyje1FKuYXxb0ZTMlZheC1jVj2msf01Uf0_HBF9n2yQuh8W293vEUBdp31soQs5Za035BeRW4Opug99lA-nDNIbg-jWsxXyv-EWQRoGMt9F6dMCi7kiAaoyAe-glk3NU52TTq5Ss4BeQ&h=PlDBztzjmt-KdSYIEGEI0BqqvdPDohKMNmCt6h2prCw + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Cache-Control: + - no-cache + Content-Length: + - "0" + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Ratelimit-Remaining-Subscription-Global-Reads: + - "16499" + X-Msedge-Ref: + - 'Ref A: CC216CE95FDE45B7A781092B2A5872DE Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:58:29Z' + status: 200 OK + code: 200 + duration: 247.284946ms + - id: 39 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: management.azure.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept: + - application/json + Test-Request-Attempt: + - "0" + url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/asotest-rg-cnnagh/providers/Microsoft.ContainerService/managedClusters/asotest-mc-qtrqym?api-version=2021-05-01 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 109 + uncompressed: false + body: '{"error":{"code":"ResourceGroupNotFound","message":"Resource group ''asotest-rg-cnnagh'' could not be found."}}' + headers: + Cache-Control: + - no-cache + Content-Length: + - "109" + Content-Type: + - application/json; charset=utf-8 + Expires: + - "-1" + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Cache: + - CONFIG_NOCACHE + X-Content-Type-Options: + - nosniff + X-Ms-Failure-Cause: + - gateway + X-Msedge-Ref: + - 'Ref A: C71C0AF34A95435680C9BDACA1ADD32A Ref B: CO6AA3150219033 Ref C: 2024-10-29T23:58:31Z' + status: 404 Not Found + code: 404 + duration: 111.090377ms diff --git a/v2/internal/crdmanagement/helpers_test.go b/v2/internal/crdmanagement/helpers_test.go index 14e4ec9d9da..ef2a4855212 100644 --- a/v2/internal/crdmanagement/helpers_test.go +++ b/v2/internal/crdmanagement/helpers_test.go @@ -136,5 +136,6 @@ func (t *testData) getKnownStorageTypes() ([]*registration.StorageType, error) { nil, // Not used for this test t.kubeClient, nil, // Not used for this test + nil, // Not used for this test generic.Options{}) } diff --git a/v2/internal/reconcilers/arm/azure_generic_arm_reconciler.go b/v2/internal/reconcilers/arm/azure_generic_arm_reconciler.go index c8ec86601e3..8d94bdcd193 100644 --- a/v2/internal/reconcilers/arm/azure_generic_arm_reconciler.go +++ b/v2/internal/reconcilers/arm/azure_generic_arm_reconciler.go @@ -17,6 +17,7 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/config" "github.com/Azure/azure-service-operator/v2/internal/reconcilers" "github.com/Azure/azure-service-operator/v2/internal/resolver" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" @@ -63,6 +64,7 @@ func NewAzureDeploymentReconciler( kubeClient kubeclient.Client, resourceResolver *resolver.Resolver, positiveConditions *conditions.PositiveConditionBuilder, + expressionEvaluator asocel.ExpressionEvaluator, cfg config.Values, extension genruntime.ResourceExtension, ) *AzureDeploymentReconciler { @@ -76,8 +78,9 @@ func NewAzureDeploymentReconciler( ARMOwnedResourceReconcilerCommon: reconcilers.ARMOwnedResourceReconcilerCommon{ ResourceResolver: resourceResolver, ReconcilerCommon: reconcilers.ReconcilerCommon{ - KubeClient: kubeClient, - PositiveConditions: positiveConditions, + KubeClient: kubeClient, + PositiveConditions: positiveConditions, + ExpressionEvaluator: expressionEvaluator, }, }, } diff --git a/v2/internal/reconcilers/arm/azure_generic_arm_reconciler_instance.go b/v2/internal/reconcilers/arm/azure_generic_arm_reconciler_instance.go index 2242a83f317..a132021fe9b 100644 --- a/v2/internal/reconcilers/arm/azure_generic_arm_reconciler_instance.go +++ b/v2/internal/reconcilers/arm/azure_generic_arm_reconciler_instance.go @@ -668,12 +668,17 @@ func (r *azureDeploymentReconcilerInstance) saveAssociatedKubernetesResources(ct var resources []client.Object + // Special case, because we need to find what secrets the secretExpressionExporter needs and get those secrets + additionalSecrets, err := findRequiredSecrets(r.ExpressionEvaluator, r.Obj, originalVersion) + if err != nil { + return errors.Wrapf(err, "error finding required secrets") + } secretExporter := &kubernetesSecretExporter{ obj: r.Obj, connection: r.ARMConnection, log: r.Log, extension: r.Extension, - additionalSecrets: nil, // TODO: Will be filled in in a subsequent PR + additionalSecrets: additionalSecrets, } var additionalResources []client.Object @@ -695,14 +700,24 @@ func (r *azureDeploymentReconcilerInstance) saveAssociatedKubernetesResources(ct log: r.Log, connection: r.ARMConnection, }, + &configMapExpressionExporter{ + obj: r.Obj, + versionedObj: originalVersion, + expressionEvaluator: r.ExpressionEvaluator, + }, + &secretExpressionExporter{ + obj: r.Obj, + versionedObj: originalVersion, + expressionEvaluator: r.ExpressionEvaluator, + rawSecrets: secretExporter.rawSecrets, + }, } for _, exporter := range exporters { additionalResources, err = exporter.Export(ctx) if err != nil { - return errors.Wrap(err, "failed to produce resources for export") + return err } - resources = append(resources, additionalResources...) } diff --git a/v2/internal/reconcilers/arm/kubernetes_resource_exporter.go b/v2/internal/reconcilers/arm/kubernetes_resource_exporter.go index 9265066a063..6362ba89733 100644 --- a/v2/internal/reconcilers/arm/kubernetes_resource_exporter.go +++ b/v2/internal/reconcilers/arm/kubernetes_resource_exporter.go @@ -15,6 +15,7 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/set" asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/extensions" @@ -46,7 +47,8 @@ func (c *configMapExpressionExporter) Export(ctx context.Context) ([]client.Obje resources, err := c.parseConfigMaps(cmExpressions) if err != nil { - return nil, errors.Wrap(err, "failed to parse configmap expressions for export") + err = errors.Wrap(err, "failed to parse configmap expressions for export") + return nil, conditions.NewReadyConditionImpactingError(err, conditions.ConditionSeverityError, conditions.ReasonAdditionalKubernetesObjWriteFailure) } return resources, err } @@ -107,7 +109,8 @@ func (s *secretExpressionExporter) Export(ctx context.Context) ([]client.Object, } resources, err := s.parseSecrets(secretExpressions, s.versionedObj, s.rawSecrets) if err != nil { - return nil, errors.Wrap(err, "failed to parse secret expressions for export") + err = errors.Wrap(err, "failed to parse secret expressions for export") + return nil, conditions.NewReadyConditionImpactingError(err, conditions.ConditionSeverityError, conditions.ReasonAdditionalKubernetesObjWriteFailure) } return resources, nil @@ -152,9 +155,6 @@ func (s *secretExpressionExporter) parseSecrets( return secrets.SliceToClientObjectSlice(result), nil } -// TODO: This will be used in a followup PR -// -//nolint:unused func findRequiredSecrets( expressionEvaluator asocel.ExpressionEvaluator, obj genruntime.ARMMetaObject, diff --git a/v2/internal/reconcilers/common.go b/v2/internal/reconcilers/common.go index 45f96ef5fd6..9b649305d79 100644 --- a/v2/internal/reconcilers/common.go +++ b/v2/internal/reconcilers/common.go @@ -17,6 +17,7 @@ import ( . "github.com/Azure/azure-service-operator/v2/internal/logging" "github.com/Azure/azure-service-operator/v2/internal/ownerutil" "github.com/Azure/azure-service-operator/v2/internal/resolver" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/internal/util/to" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" @@ -158,8 +159,9 @@ func (r *ARMOwnedResourceReconcilerCommon) ClaimResource(ctx context.Context, lo } type ReconcilerCommon struct { - KubeClient kubeclient.Client - PositiveConditions *conditions.PositiveConditionBuilder + KubeClient kubeclient.Client + PositiveConditions *conditions.PositiveConditionBuilder + ExpressionEvaluator asocel.ExpressionEvaluator } func ClassifyResolverError(err error) error { diff --git a/v2/internal/testcommon/kube_test_context_envtest.go b/v2/internal/testcommon/kube_test_context_envtest.go index aaeb473ba88..854f873afc1 100644 --- a/v2/internal/testcommon/kube_test_context_envtest.go +++ b/v2/internal/testcommon/kube_test_context_envtest.go @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/record" + "k8s.io/klog/v2/textlogger" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" @@ -38,9 +39,11 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/config" "github.com/Azure/azure-service-operator/v2/internal/controllers" "github.com/Azure/azure-service-operator/v2/internal/identity" + "github.com/Azure/azure-service-operator/v2/internal/logging" "github.com/Azure/azure-service-operator/v2/internal/metrics" "github.com/Azure/azure-service-operator/v2/internal/reconcilers/arm" "github.com/Azure/azure-service-operator/v2/internal/reconcilers/generic" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/internal/util/interval" "github.com/Azure/azure-service-operator/v2/internal/util/kubeclient" "github.com/Azure/azure-service-operator/v2/internal/util/lockedrand" @@ -89,9 +92,10 @@ func createSharedEnvTest(cfg testConfig, namespaceResources *namespaceResources) Scheme: scheme, } - // Switch logger below if we want controller-runtime logs in the tests. + logger := textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(logging.Debug))) + + // TODO: Uncomment the below if we want controller-runtime logs in the tests. // By default we've disabled controller runtime logs because they're very verbose and usually not useful. - // logger := textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(logging.Debug))) // ctrl.SetLogger(logger) ctrl.SetLogger(logr.Discard()) @@ -182,6 +186,15 @@ func createSharedEnvTest(cfg testConfig, namespaceResources *namespaceResources) testIndexer := NewIndexer(mgr.GetScheme()) indexer := kubeclient.NewAndIndexer(mgr.GetFieldIndexer(), testIndexer) kubeClient := kubeclient.NewClient(NewClient(mgr.GetClient(), testIndexer)) + expressionEvaluator, err := asocel.NewExpressionEvaluator(asocel.Log(logger)) + // Note that we don't start expressionEvaluator here because we're in a test context and turning cache eviction + // on is probably overkill. + if err != nil { + return nil, errors.Wrapf(err, "creating expression evaluator") + } + + // This means a single evaluator will be used for all envtests. For the purposes of testing that's probably OK... + asocel.RegisterEvaluator(expressionEvaluator) credentialProviderWrapper := &credentialProviderWrapper{namespaceResources: namespaceResources} @@ -243,6 +256,7 @@ func createSharedEnvTest(cfg testConfig, namespaceResources *namespaceResources) credentialProviderWrapper, kubeClient, positiveConditions, + expressionEvaluator, options) if err != nil { return nil, err diff --git a/v2/internal/util/cel/cel.go b/v2/internal/util/cel/cel.go index 9e9aeefaa21..da538b56163 100644 --- a/v2/internal/util/cel/cel.go +++ b/v2/internal/util/cel/cel.go @@ -6,6 +6,7 @@ package cel import ( + "fmt" "reflect" "strings" @@ -143,8 +144,11 @@ func NewEnv(resource reflect.Type) (*cel.Env, error) { // The typesList of supported env functions was taken from Kubernetes here: // https://kubernetes.io/docs/reference/using-api/cel/#language-overview. + + // Note: Adding to the below list of supported functions/features should be done with caution, + // and any updates should be propagated to docs/hugo/content/guide/expressions.md as well. return cel.NewEnv( - ext.Strings(), + ext.Strings(ext.StringsVersion(3)), // At the time of writing, 3 was the latest version cel.DefaultUTCTimeZone(true), // Kubernetes specifies HomogenousAggregateLiterals, but it could cause issues for // construction of dynamic JSON payloads. This isn't a common operation, but then again @@ -162,7 +166,7 @@ func NewEnv(resource reflect.Type) (*cel.Env, error) { // TODO: https://kubernetes.io/docs/reference/using-api/cel/#kubernetes-list-library // TODO: and the Kubernetes Regex Library // TODO: https://kubernetes.io/docs/reference/using-api/cel/#kubernetes-regex-library - // TODO: if there is user need. + // TODO: if there is user need. Adding them should be non-breaking. cel.Variable("self", cel.ObjectType(selfPath)), cel.Variable("secret", cel.MapType(cel.StringType, cel.StringType)), ) @@ -272,9 +276,23 @@ var fieldEscaper = strings.NewReplacer( "__", "__underscores__", ".", "__dot__", "-", "__dash__", - "/", "__slash__") + "/", "__slash__", +) + +// These keywords come from https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax +// Note that we ONLY escape keywords that are part of CEL syntax, not keywords reserved for embedding. +var reservedKeywords = set.Make( + "true", + "false", + "null", + "in", +) func escapeFieldName(field string) string { + if reservedKeywords.Contains(field) { + return fmt.Sprintf("__%s__", field) + } + return fieldEscaper.Replace(field) } diff --git a/v2/internal/util/cel/cel_test.go b/v2/internal/util/cel/cel_test.go index 557bea77e87..77e2de67427 100644 --- a/v2/internal/util/cel/cel_test.go +++ b/v2/internal/util/cel/cel_test.go @@ -54,15 +54,24 @@ type SimpleSpec2 struct { DashField string `json:"dash-field,omitempty"` DashUnderscoreField string `json:"dash-__field,omitempty"` + Slice []string `json:"slice,omitempty"` + // odata.type is the only field I'm seeing in ASO that has this format, and there aren't many of those DotField string `json:"dot.field,omitempty"` // There aren't currently any fields in ASO that have this format, but testing it here anyway just to be safe SlashField string `json:"slash/field,omitempty"` - Const string `json:"const,omitempty"` // This is a CEL keyword - Break string `json:"break,omitempty"` // This is a CEL keyword - Loop string `json:"loop,omitempty"` // This is a CEL keyword + Const string `json:"const,omitempty"` // This is a CEL reserved word to enable easier embedding + Break string `json:"break,omitempty"` // This is a CEL reserved word to enable easier embedding + False string `json:"false,omitempty"` // This is a CEL reserved word + True string `json:"true,omitempty"` // This is a CEL reserved word + In string `json:"in,omitempty"` // This is a CEL reserved word + Null string `json:"null,omitempty"` // This is a CEL reserved word + Int string `json:"int,omitempty"` // This ISN'T a CEL reserved word + String string `json:"string,omitempty"` // This ISN'T a CEL reserved word + EndsWith string `json:"endsWith,omitempty"` // This ISN'T a CEL reserved word + Namespace string `json:"namespace,omitempty"` // This is a CEL reserved word to enable easier embedding } type SimpleStatus2 struct { @@ -133,6 +142,17 @@ func Test_CompileAndRunAndCheck(t *testing.T) { expression: `7`, expectedErr: "expression \"7\" must return one of [string,map(string, string)], but was int", }, + { + name: "direct map output", + self: newSimpleResource(), + expression: `self.metadata.annotations`, + expectedStr: "hello-help", + expectedMap: map[string]string{ + "pizza": "no", + "fruit": "yes", + "cookie": "yes", + }, + }, { name: "unstructured type simple string output", self: newSimpleResource2Customized( @@ -198,6 +218,19 @@ func Test_CompileAndRunAndCheck(t *testing.T) { expression: `string(self.spec.untyped.nestedStruct.mode)`, // There is no mode type expectedErr: "failed to eval CEL expression: \"string(self.spec.untyped.nestedStruct.mode)\": no such key: mode", }, + { + name: "slice comprehension", + self: newSimpleResource2Customized( + func(r *SimpleResource2) { + r.Spec.Slice = []string{ + "hello", + "world", + "help", + } + }), + expression: `self.spec.slice.filter(a, a.startsWith("hel")).join("-")`, + expectedStr: "hello-help", + }, { name: "simple secret access", self: newSimpleResource(), @@ -298,15 +331,22 @@ func Test_CompileAndRunAndCheck(t *testing.T) { expectedStr: "hello", }, { - name: "reserved fields works as expected", + name: "reserved fields and functions work as expected", self: newSimpleResource2Customized( func(r *SimpleResource2) { - r.Spec.Const = "hello" - r.Spec.Break = " there" - r.Spec.Loop = " friend" + r.Spec.Const = "hello! " + r.Spec.Break = "hello! " + r.Spec.False = "This " + r.Spec.True = "is " + r.Spec.In = "a " + r.Spec.Null = "test. " + r.Spec.EndsWith = "I" + r.Spec.String = " hope" + r.Spec.Int = " it" + r.Spec.Namespace = " works." }), - expression: `self.spec.const + self.spec.break + self.spec.loop`, - expectedStr: "hello there friend", + expression: `self.spec.const + self.spec.break + self.spec.__false__ + self.spec.__true__ + self.spec.__in__ + self.spec.__null__ + self.spec.endsWith + self.spec.string + self.spec.int + self.spec.namespace`, + expectedStr: "hello! hello! This is a test. I hope it works.", }, } @@ -509,6 +549,11 @@ func newSimpleResource() *SimpleResource { ObjectMeta: metav1.ObjectMeta{ Name: "mysimpleresource", Namespace: "default", + Annotations: map[string]string{ + "pizza": "no", + "fruit": "yes", + "cookie": "yes", + }, }, Spec: SimpleSpec{ Location: "eastus", diff --git a/v2/pkg/genruntime/configmaps/collector.go b/v2/pkg/genruntime/configmaps/collector.go index 8e242d60b9e..adb51477cb0 100644 --- a/v2/pkg/genruntime/configmaps/collector.go +++ b/v2/pkg/genruntime/configmaps/collector.go @@ -53,11 +53,11 @@ func (c *Collector) get(dest *genruntime.ConfigMapDestination) *v1.ConfigMap { func (c *Collector) errIfKeyExists(val *v1.ConfigMap, key string) error { if _, ok := val.Data[key]; ok { - return errors.Errorf("key collision, entry exists for key %s in Data", key) + return errors.Errorf("key collision, entry exists for key '%s' in Data", key) } if _, ok := val.BinaryData[key]; ok { - return errors.Errorf("key collision, entry exists for key %s in BinaryData", key) + return errors.Errorf("key collision, entry exists for key '%s' in BinaryData", key) } return nil diff --git a/v2/pkg/genruntime/configmaps/validation.go b/v2/pkg/genruntime/configmaps/validation.go index 9c97ae5dba2..288d23a55bb 100644 --- a/v2/pkg/genruntime/configmaps/validation.go +++ b/v2/pkg/genruntime/configmaps/validation.go @@ -10,10 +10,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/Azure/azure-service-operator/v2/internal/set" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" ) +// For unit testing purposes +var expressionEvaluator = asocel.Evaluator + type keyPair struct { name string key string @@ -21,12 +25,8 @@ type keyPair struct { // ValidateDestinations checks that no two destinations are writing to the same configmap/key, as that could cause // those values to overwrite one another. -func ValidateDestinations(destinations []*genruntime.ConfigMapDestination) (admission.Warnings, error) { - return ValidateDestinationsExt(destinations, nil) -} - -// TODO: ValidateDestinationsExt will replace ValidateDestinations in a future PR. -func ValidateDestinationsExt( +func ValidateDestinations( + self any, destinations []*genruntime.ConfigMapDestination, destinationExpressions []*core.DestinationExpression, ) (admission.Warnings, error) { @@ -48,17 +48,37 @@ func ValidateDestinationsExt( locations.Add(pair) } + celEvaluator := expressionEvaluator() + for _, dest := range destinationExpressions { if dest == nil { continue } + // Evaluator may be nil in some cases, if it is don't use it + if celEvaluator != nil { + // Validate that the expression is a valid CEL expression + outputType, err := celEvaluator.Check(dest.Value, self) + if err != nil { + // Error should already have enough context + return nil, err + } + + if outputType.IsExactType(asocel.StringType) && dest.Key == "" { + return nil, errors.Errorf("CEL expression with output type string must specify destination 'key', %s", dest.String()) + } + if outputType.IsExactType(asocel.MapType) && dest.Key != "" { + return nil, errors.Errorf("CEL expression with output type map[string]string must not specify destination 'key', %s", dest.String()) + } + } + if dest.Key == "" { - // TODO: Key may be empty because of map[string]string supported exports. - // TODO: We should validate that in more depth but need a CEL parser to do so. continue } + // Validate no destination collisions. Note that we can't check collisions for map keys because to do that + // we'd have to actually evaluate the CEL expression which we can't do yet as it may be dependent on + // things like .status fields which aren't yet filled out in the resource. pair := keyPair{ name: dest.Name, key: dest.Key, diff --git a/v2/pkg/genruntime/configmaps/validation_test.go b/v2/pkg/genruntime/configmaps/validation_test.go index ab49d477b12..4be03c368dc 100644 --- a/v2/pkg/genruntime/configmaps/validation_test.go +++ b/v2/pkg/genruntime/configmaps/validation_test.go @@ -19,7 +19,7 @@ func Test_ValidateConfigMapDestination_EmptyListValidates(t *testing.T) { t.Parallel() g := NewGomegaWithT(t) - warnings, err := configmaps.ValidateDestinationsExt(nil, nil) + warnings, err := configmaps.ValidateDestinations(nil, nil, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -33,7 +33,7 @@ func Test_ValidateConfigMapDestination_ListWithNilElementsValidates(t *testing.T nil, } - warnings, err := configmaps.ValidateDestinationsExt(destinations, nil) + warnings, err := configmaps.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -47,7 +47,7 @@ func Test_ValidateConfigMapDestinationExpressions_ListWithNilElementsValidates(t nil, } - warnings, err := configmaps.ValidateDestinationsExt(nil, destinations) + warnings, err := configmaps.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -60,7 +60,7 @@ func Test_ValidateConfigMapDestination_LengthOneListValidates(t *testing.T) { {Name: "n1", Key: "key1"}, } - warnings, err := configmaps.ValidateDestinationsExt(destinations, nil) + warnings, err := configmaps.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -73,7 +73,7 @@ func Test_ValidateConfigMapDestinationExpressions_LengthOneListValidates(t *test {Name: "n1", Key: "key1", Value: "resource.status.id"}, } - warnings, err := configmaps.ValidateDestinationsExt(nil, destinations) + warnings, err := configmaps.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -89,7 +89,7 @@ func Test_ValidateConfigMapDestination_ListWithoutCollisionsValidates(t *testing {Name: "n1", Key: "key4"}, } - warnings, err := configmaps.ValidateDestinationsExt(destinations, nil) + warnings, err := configmaps.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -105,7 +105,7 @@ func Test_ValidateConfigMapDestinationExpressions_ListWithoutCollisionsValidates {Name: "n1", Key: "key4", Value: "resource.status.id"}, } - warnings, err := configmaps.ValidateDestinationsExt(nil, destinations) + warnings, err := configmaps.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -121,7 +121,7 @@ func Test_ValidateConfigMapDestination_ListWithDifferentCasesValidates(t *testin {Name: "n1", Key: "key4"}, } - warnings, err := configmaps.ValidateDestinationsExt(destinations, nil) + warnings, err := configmaps.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -136,7 +136,7 @@ func Test_ValidateConfigMapDestination_ListWithCollisionsFailsValidation(t *test {Name: "n3", Key: "key1"}, {Name: "n1", Key: "key1"}, } - _, err := configmaps.ValidateDestinationsExt(destinations, nil) + _, err := configmaps.ValidateDestinations(nil, destinations, nil) g.Expect(err).ToNot(BeNil()) g.Expect(err.Error()).To(Equal("cannot write more than one configmap value to destination Name: \"n1\", Key: \"key1\"")) } @@ -157,7 +157,7 @@ func Test_ValidateConfigMapDestinationAndExpressions_CollisionBetweenEachFailsVa {Name: "n3", Key: "key1", Value: "resource.status.id"}, } - _, err := configmaps.ValidateDestinationsExt(destinations, destinationExpressions) + _, err := configmaps.ValidateDestinations(nil, destinations, destinationExpressions) g.Expect(err).ToNot(BeNil()) g.Expect(err.Error()).To(Equal("cannot write more than one configmap value to destination Name: \"n3\", Key: \"key1\", Value: \"resource.status.id\"")) } @@ -171,7 +171,7 @@ func Test_ValidateConfigMapDestinationExpressions_EmptyKeyIgnored(t *testing.T) {Name: "n1", Key: "key1", Value: "resource.status.id"}, } - warnings, err := configmaps.ValidateDestinationsExt(nil, destinations) + warnings, err := configmaps.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } diff --git a/v2/pkg/genruntime/configmaps/validation_unexported_test.go b/v2/pkg/genruntime/configmaps/validation_unexported_test.go new file mode 100644 index 00000000000..93940bf7503 --- /dev/null +++ b/v2/pkg/genruntime/configmaps/validation_unexported_test.go @@ -0,0 +1,74 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +package configmaps + +import ( + "testing" + + . "github.com/onsi/gomega" + + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" +) + +type Self struct{} + +// Can't run in parallel because it's mocking a package scope variable +// +//nolint:paralleltest +func Test_ValidateConfigMapDestination_MissingKey(t *testing.T) { + g := NewGomegaWithT(t) + + evaluator, err := asocel.NewExpressionEvaluator() + g.Expect(err).ToNot(HaveOccurred()) + expressionEvaluator = func() asocel.ExpressionEvaluator { + return evaluator + } + defer func() { + expressionEvaluator = asocel.Evaluator + }() + + warnings, err := ValidateDestinations( + &Self{}, + nil, + []*core.DestinationExpression{ + { + Name: "my-configmap", + Value: `"hello"`, + }, + }) + g.Expect(warnings).To(BeNil()) + g.Expect(err).To(MatchError(ContainSubstring("CEL expression with output type string must specify destination 'key'"))) +} + +// Can't run in parallel because it's mocking a package scope variable +// +//nolint:paralleltest +func Test_ValidateConfigMapDestination_UnneededKey(t *testing.T) { + g := NewGomegaWithT(t) + + evaluator, err := asocel.NewExpressionEvaluator() + g.Expect(err).ToNot(HaveOccurred()) + expressionEvaluator = func() asocel.ExpressionEvaluator { + return evaluator + } + defer func() { + expressionEvaluator = asocel.Evaluator + }() + + warnings, err := ValidateDestinations( + &Self{}, + nil, + []*core.DestinationExpression{ + { + Name: "my-configmap", + Key: "my-key", + Value: `{"test": "test"}`, + }, + }) + g.Expect(warnings).To(BeNil()) + g.Expect(err).To(MatchError(ContainSubstring("CEL expression with output type map[string]string must not specify destination 'key'"))) +} diff --git a/v2/pkg/genruntime/core/destination_expression.go b/v2/pkg/genruntime/core/destination_expression.go index e92c2e3b3aa..8c1c4cbe79c 100644 --- a/v2/pkg/genruntime/core/destination_expression.go +++ b/v2/pkg/genruntime/core/destination_expression.go @@ -25,7 +25,8 @@ type DestinationExpression struct { // map[string]string. Key string `json:"key,omitempty"` - // Value is a CEL expression. The CEL expression may return a string or a map[string]string. For more information see TODO (improve this) + // Value is a CEL expression. The CEL expression may return a string or a map[string]string. For more information + // on CEL in ASO see https://azure.github.io/azure-service-operator/guide/expressions/ // +kubebuilder:validation:Required Value string `json:"value,omitempty"` } diff --git a/v2/pkg/genruntime/merger/merger.go b/v2/pkg/genruntime/merger/merger.go index 3c2da215fa0..69306f5ce98 100644 --- a/v2/pkg/genruntime/merger/merger.go +++ b/v2/pkg/genruntime/merger/merger.go @@ -30,12 +30,12 @@ func MergeObjects(objs []client.Object) ([]client.Object, error) { switch typedObj := obj.(type) { case *v1.Secret: if namespace != obj.GetNamespace() { - return nil, errors.Errorf("cannot merge objects from different namespaces: %s : %s", namespace, obj.GetNamespace()) + return nil, errors.Errorf("cannot merge objects from different namespaces: '%s' : '%s'", namespace, obj.GetNamespace()) } secretSlice = append(secretSlice, typedObj) case *v1.ConfigMap: if namespace != obj.GetNamespace() { - return nil, errors.Errorf("cannot merge objects from different namespaces: %s : %s", namespace, obj.GetNamespace()) + return nil, errors.Errorf("cannot merge objects from different namespaces: '%s' : '%s'", namespace, obj.GetNamespace()) } configMapSlice = append(configMapSlice, typedObj) default: diff --git a/v2/pkg/genruntime/merger/merger_test.go b/v2/pkg/genruntime/merger/merger_test.go index 4e3b1ace42a..c5603e4c4cf 100644 --- a/v2/pkg/genruntime/merger/merger_test.go +++ b/v2/pkg/genruntime/merger/merger_test.go @@ -144,7 +144,7 @@ func TestMerge_SameDestinationKey_ReturnsError(t *testing.T) { configMapC2, }) g.Expect(err).To(HaveOccurred()) - g.Expect(err.Error()).To(Equal("failed merging secrets: key collision, entry exists for key key1 in StringData")) + g.Expect(err.Error()).To(Equal("failed merging secrets: key collision, entry exists for key 'key1' in StringData")) } func TestMerge_DifferentNamespaces_ReturnsError(t *testing.T) { @@ -157,5 +157,5 @@ func TestMerge_DifferentNamespaces_ReturnsError(t *testing.T) { configMapC1, }) g.Expect(err).To(HaveOccurred()) - g.Expect(err.Error()).To(Equal("cannot merge objects from different namespaces: testnamespace : othernamespace")) + g.Expect(err.Error()).To(Equal("cannot merge objects from different namespaces: 'testnamespace' : 'othernamespace'")) } diff --git a/v2/pkg/genruntime/secrets/collector.go b/v2/pkg/genruntime/secrets/collector.go index ec7c14ef9fc..fafc0f5219a 100644 --- a/v2/pkg/genruntime/secrets/collector.go +++ b/v2/pkg/genruntime/secrets/collector.go @@ -54,11 +54,11 @@ func (c *Collector) get(dest *genruntime.SecretDestination) *v1.Secret { func (c *Collector) errIfKeyExists(val *v1.Secret, key string) error { if _, ok := val.StringData[key]; ok { - return errors.Errorf("key collision, entry exists for key %s in StringData", key) + return errors.Errorf("key collision, entry exists for key '%s' in StringData", key) } if _, ok := val.Data[key]; ok { - return errors.Errorf("key collision, entry exists for key %s in Data", key) + return errors.Errorf("key collision, entry exists for key '%s' in Data", key) } return nil diff --git a/v2/pkg/genruntime/secrets/validation.go b/v2/pkg/genruntime/secrets/validation.go index 75f8a6955c5..81b4371b112 100644 --- a/v2/pkg/genruntime/secrets/validation.go +++ b/v2/pkg/genruntime/secrets/validation.go @@ -10,10 +10,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/Azure/azure-service-operator/v2/internal/set" + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" ) +// For unit testing purposes +var expressionEvaluator = asocel.Evaluator + type keyPair struct { name string key string @@ -21,12 +25,8 @@ type keyPair struct { // ValidateDestinations checks that no two destinations are writing to the same secret/key, as that could cause // those secrets to overwrite one another. -func ValidateDestinations(destinations []*genruntime.SecretDestination) (admission.Warnings, error) { - return ValidateDestinationsExt(destinations, nil) -} - -// TODO: ValidateDestinationsExt will replace ValidateDestinations in a future PR. -func ValidateDestinationsExt( +func ValidateDestinations( + self any, destinations []*genruntime.SecretDestination, destinationExpressions []*core.DestinationExpression, ) (admission.Warnings, error) { @@ -49,17 +49,36 @@ func ValidateDestinationsExt( locations.Add(pair) } + celEvaluator := expressionEvaluator() + for _, dest := range destinationExpressions { if dest == nil { continue } + if celEvaluator != nil { + // Validate that the expression is a valid CEL expression + outputType, err := celEvaluator.Check(dest.Value, self) + if err != nil { + // Error should already have enough context + return nil, err + } + + if outputType.IsExactType(asocel.StringType) && dest.Key == "" { + return nil, errors.Errorf("CEL expression with output type string must specify destination 'key', %s", dest.String()) + } + if outputType.IsExactType(asocel.MapType) && dest.Key != "" { + return nil, errors.Errorf("CEL expression with output type map[string]string must not specify destination 'key', %s", dest.String()) + } + } + if dest.Key == "" { - // TODO: Key may be empty because of map[string]string supported exports. - // TODO: We should validate that in more depth but need a CEL parser to do so. continue } + // Validate no destination collisions. Note that we can't check collisions for map keys because to do that + // we'd have to actually evaluate the CEL expression which we can't do yet as it may be dependent on + // things like .status fields which aren't yet filled out in the resource. pair := keyPair{ name: dest.Name, key: dest.Key, @@ -67,7 +86,6 @@ func ValidateDestinationsExt( if locations.Contains(pair) { return nil, errors.Errorf("cannot write more than one secret to destination %s", dest.String()) } - locations.Add(pair) } diff --git a/v2/pkg/genruntime/secrets/validation_test.go b/v2/pkg/genruntime/secrets/validation_test.go index 16cc489cd97..a5cf1a17e6c 100644 --- a/v2/pkg/genruntime/secrets/validation_test.go +++ b/v2/pkg/genruntime/secrets/validation_test.go @@ -19,7 +19,7 @@ func Test_ValidateSecretDestination_EmptyListValidates(t *testing.T) { t.Parallel() g := NewGomegaWithT(t) - warnings, err := secrets.ValidateDestinationsExt(nil, nil) + warnings, err := secrets.ValidateDestinations(nil, nil, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -33,7 +33,7 @@ func Test_ValidateSecretDestination_ListWithNilElementsValidates(t *testing.T) { nil, } - warnings, err := secrets.ValidateDestinationsExt(destinations, nil) + warnings, err := secrets.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -47,7 +47,7 @@ func Test_ValidateSecretDestinationExpressions_ListWithNilElementsValidates(t *t nil, } - warnings, err := secrets.ValidateDestinationsExt(nil, destinations) + warnings, err := secrets.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -60,7 +60,7 @@ func Test_ValidateSecretDestination_LengthOneListValidates(t *testing.T) { {Name: "n1", Key: "key1"}, } - warnings, err := secrets.ValidateDestinationsExt(destinations, nil) + warnings, err := secrets.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -73,7 +73,7 @@ func Test_ValidateSecretDestinationExpressions_LengthOneListValidates(t *testing {Name: "n1", Key: "key1", Value: "resource.status.id"}, } - warnings, err := secrets.ValidateDestinationsExt(nil, destinations) + warnings, err := secrets.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -89,7 +89,7 @@ func Test_ValidateSecretDestination_ListWithoutCollisionsValidates(t *testing.T) {Name: "n1", Key: "key4"}, } - warnings, err := secrets.ValidateDestinationsExt(destinations, nil) + warnings, err := secrets.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -105,7 +105,7 @@ func Test_ValidateSecretDestinationExpressions_ListWithoutCollisionsValidates(t {Name: "n1", Key: "key4", Value: "resource.status.id"}, } - warnings, err := secrets.ValidateDestinationsExt(nil, destinations) + warnings, err := secrets.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -121,7 +121,7 @@ func Test_ValidateSecretDestination_ListWithDifferentCasesValidates(t *testing.T {Name: "n1", Key: "key4"}, } - warnings, err := secrets.ValidateDestinationsExt(destinations, nil) + warnings, err := secrets.ValidateDestinations(nil, destinations, nil) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } @@ -137,7 +137,7 @@ func Test_ValidateSecretDestination_ListWithCollisionsFailsValidation(t *testing {Name: "n1", Key: "key1"}, } - _, err := secrets.ValidateDestinationsExt(destinations, nil) + _, err := secrets.ValidateDestinations(nil, destinations, nil) g.Expect(err).ToNot(BeNil()) g.Expect(err.Error()).To(Equal("cannot write more than one secret to destination Name: \"n1\", Key: \"key1\"")) } @@ -158,7 +158,7 @@ func Test_ValidateSecretDestinationAndExpressions_CollisionBetweenEachFailsValid {Name: "n3", Key: "key1", Value: "resource.status.id"}, } - _, err := secrets.ValidateDestinationsExt(destinations, destinationExpressions) + _, err := secrets.ValidateDestinations(nil, destinations, destinationExpressions) g.Expect(err).ToNot(BeNil()) g.Expect(err.Error()).To(Equal("cannot write more than one secret to destination Name: \"n3\", Key: \"key1\", Value: \"resource.status.id\"")) } @@ -172,7 +172,7 @@ func Test_ValidateSecretDestinationExpressions_EmptyKeyIgnored(t *testing.T) { {Name: "n1", Key: "key1", Value: "resource.status.id"}, } - warnings, err := secrets.ValidateDestinationsExt(nil, destinations) + warnings, err := secrets.ValidateDestinations(nil, nil, destinations) g.Expect(warnings).To(BeNil()) g.Expect(err).To(BeNil()) } diff --git a/v2/pkg/genruntime/secrets/validation_unexported_test.go b/v2/pkg/genruntime/secrets/validation_unexported_test.go new file mode 100644 index 00000000000..5471949386d --- /dev/null +++ b/v2/pkg/genruntime/secrets/validation_unexported_test.go @@ -0,0 +1,74 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +package secrets + +import ( + "testing" + + . "github.com/onsi/gomega" + + asocel "github.com/Azure/azure-service-operator/v2/internal/util/cel" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" +) + +type Self struct{} + +// Can't run in parallel because it's mocking a package scope variable +// +//nolint:paralleltest +func Test_ValidateConfigMapDestination_MissingKey(t *testing.T) { + g := NewGomegaWithT(t) + + evaluator, err := asocel.NewExpressionEvaluator() + g.Expect(err).ToNot(HaveOccurred()) + expressionEvaluator = func() asocel.ExpressionEvaluator { + return evaluator + } + defer func() { + expressionEvaluator = asocel.Evaluator + }() + + warnings, err := ValidateDestinations( + &Self{}, + nil, + []*core.DestinationExpression{ + { + Name: "my-configmap", + Value: `"hello"`, + }, + }) + g.Expect(warnings).To(BeNil()) + g.Expect(err).To(MatchError(ContainSubstring("CEL expression with output type string must specify destination 'key'"))) +} + +// Can't run in parallel because it's mocking a package scope variable +// +//nolint:paralleltest +func Test_ValidateConfigMapDestination_UnneededKey(t *testing.T) { + g := NewGomegaWithT(t) + + evaluator, err := asocel.NewExpressionEvaluator() + g.Expect(err).ToNot(HaveOccurred()) + expressionEvaluator = func() asocel.ExpressionEvaluator { + return evaluator + } + defer func() { + expressionEvaluator = asocel.Evaluator + }() + + warnings, err := ValidateDestinations( + &Self{}, + nil, + []*core.DestinationExpression{ + { + Name: "my-configmap", + Key: "my-key", + Value: `{"test": "test"}`, + }, + }) + g.Expect(warnings).To(BeNil()) + g.Expect(err).To(MatchError(ContainSubstring("CEL expression with output type map[string]string must not specify destination 'key'"))) +} diff --git a/v2/tools/generator/internal/astmodel/std_properties.go b/v2/tools/generator/internal/astmodel/std_properties.go index 5f23d9c540c..c718b824846 100644 --- a/v2/tools/generator/internal/astmodel/std_properties.go +++ b/v2/tools/generator/internal/astmodel/std_properties.go @@ -7,19 +7,21 @@ package astmodel // These are some magical field names which we're going to use or generate const ( - APIVersionProperty = "APIVersion" // Used by armconversion package - AzureNameProperty = "AzureName" - NameProperty = "Name" // Used by armconversion package - OwnerProperty = "Owner" - SetAzureNameFunc = "SetAzureName" - TypeProperty = "Type" // Used by armconversion package - OperatorSpecProperty = "OperatorSpec" - OperatorSpecSecretsProperty = "Secrets" - OperatorSpecConfigMapsProperty = "ConfigMaps" - ConditionsProperty = "Conditions" - OptionalConfigMapReferenceSuffix = "FromConfig" - UserAssignedIdentitiesProperty = "UserAssignedIdentities" - UserAssignedIdentitiesTypeName = "UserAssignedIdentityDetails" + APIVersionProperty = "APIVersion" // Used by armconversion package + AzureNameProperty = "AzureName" + NameProperty = "Name" // Used by armconversion package + OwnerProperty = "Owner" + SetAzureNameFunc = "SetAzureName" + TypeProperty = "Type" // Used by armconversion package + OperatorSpecProperty = "OperatorSpec" + OperatorSpecSecretsProperty = "Secrets" + OperatorSpecSecretExpressionsProperty = "SecretExpressions" + OperatorSpecConfigMapsProperty = "ConfigMaps" + OperatorSpecConfigMapExpressionsProperty = "ConfigMapExpressions" + ConditionsProperty = "Conditions" + OptionalConfigMapReferenceSuffix = "FromConfig" + UserAssignedIdentitiesProperty = "UserAssignedIdentities" + UserAssignedIdentitiesTypeName = "UserAssignedIdentityDetails" ) // IsKubernetesResourceProperty returns true if the supplied property name is one of the properties required by the diff --git a/v2/tools/generator/internal/astmodel/std_references.go b/v2/tools/generator/internal/astmodel/std_references.go index ff82223046f..1550063e17f 100644 --- a/v2/tools/generator/internal/astmodel/std_references.go +++ b/v2/tools/generator/internal/astmodel/std_references.go @@ -23,6 +23,7 @@ var ( // References to our Libraries GenRuntimeReference = MakeExternalPackageReference(genRuntimePathPrefix) + GenRuntimeCoreReference = MakeExternalPackageReference(genRuntimePathPrefix + "/core") GenRuntimeConditionsReference = MakeExternalPackageReference(genRuntimePathPrefix + "/conditions") GenRuntimeRegistrationReference = MakeExternalPackageReference(genRuntimePathPrefix + "/registration") ReflectHelpersReference = MakeExternalPackageReference(reflectHelpersPath) @@ -88,6 +89,9 @@ var ( ImportableResourceType = MakeExternalTypeName(GenRuntimeReference, "ImportableResource") ResourceOperationType = MakeExternalTypeName(GenRuntimeReference, "ResourceOperation") ResourceOperationTypeArray = NewArrayType(ResourceOperationType) + DestinationExpressionType = MakeExternalTypeName(GenRuntimeCoreReference, "DestinationExpression") + ConfigMapExporterType = MakeExternalTypeName(GenRuntimeConfigMapsReference, "Exporter") + SecretExporterType = MakeExternalTypeName(GenRuntimeSecretsReference, "Exporter") // Optional types - GenRuntime OptionalConfigMapReferenceType = NewOptionalType(ConfigMapReferenceType) @@ -99,6 +103,9 @@ var ( // Predeclared maps MapOfStringStringType = NewMapType(StringType, StringType) + // Predeclared slices + DestinationExpressionCollectionType = NewArrayType(NewOptionalType(DestinationExpressionType)) + // Type names - Generic ARM client GenericClientType = MakeExternalTypeName(GenericARMClientReference, "GenericClient") diff --git a/v2/tools/generator/internal/codegen/pipeline/add_operator_spec.go b/v2/tools/generator/internal/codegen/pipeline/add_operator_spec.go index e366f238742..dff847b5ad1 100644 --- a/v2/tools/generator/internal/codegen/pipeline/add_operator_spec.go +++ b/v2/tools/generator/internal/codegen/pipeline/add_operator_spec.go @@ -15,6 +15,7 @@ import ( "github.com/Azure/azure-service-operator/v2/tools/generator/internal/astmodel" "github.com/Azure/azure-service-operator/v2/tools/generator/internal/config" + "github.com/Azure/azure-service-operator/v2/tools/generator/internal/functions" ) const AddOperatorSpecStageID = "addOperatorSpec" @@ -37,6 +38,21 @@ func AddOperatorSpec(configuration *config.Configuration, idFactory astmodel.Ide } result.AddTypes(newDefs) exportedTypeNameConfigMaps.Add(resource.Name(), exportedConfigMaps) + + // Add the DynamicConfigMapExporter and DynamicSecretExporter to the resources which need it + rt := resource.Type().(*astmodel.ResourceType) + dynamicConfigMapExporter := functions.NewConfigMapExporterInterface( + resource.Name(), + rt, + idFactory) + dynamicSecretExporter := functions.NewSecretsExporterInterface( + resource.Name(), + rt, + idFactory) + + rt = rt.WithInterface(dynamicConfigMapExporter.ToInterfaceImplementation()) + rt = rt.WithInterface(dynamicSecretExporter.ToInterfaceImplementation()) + result.Add(resource.WithType(rt)) } // confirm that operator spec specific configuration was used. Note that this also indirectly confirms that @@ -78,10 +94,10 @@ func createOperatorSpecIfNeeded( } // Look up Azure generated secrets for this resource - secrets, hasSecrets := configuration.ObjectModelConfiguration.AzureGeneratedSecrets.Lookup(resolved.ResourceDef.Name()) + secrets, _ := configuration.ObjectModelConfiguration.AzureGeneratedSecrets.Lookup(resolved.ResourceDef.Name()) // Look up custom operatorSpec properties for this resource - operatorSpecProperties, hasOperatorSpecProperties := configuration.ObjectModelConfiguration.OperatorSpecProperties.Lookup(resolved.ResourceDef.Name()) + operatorSpecProperties, _ := configuration.ObjectModelConfiguration.OperatorSpecProperties.Lookup(resolved.ResourceDef.Name()) // Lookup any properties that might be exported to config maps configs, exportedProperties, err := getConfigMapProperties(defs, configuration, resource) @@ -89,16 +105,11 @@ func createOperatorSpecIfNeeded( return nil, nil, errors.Wrapf(err, "finding properties allowed to export as config maps") } - hasConfigMapProperties := len(configs) != 0 - - if !hasSecrets && !hasConfigMapProperties && !hasOperatorSpecProperties { - // We don't need to make an OperatorSpec type - return nil, nil, nil - } - builder := newOperatorSpecBuilder(configuration, idFactory, resolved.ResourceDef) - builder.addSecretsToOperatorSpec(secrets) + builder.addSecrets(secrets) builder.addConfigs(configs) + builder.addDynamicSecrets() + builder.addDynamicConfigMaps() builder.addCustomProperties(operatorSpecProperties) operatorSpec, err := builder.build() @@ -332,29 +343,46 @@ func (b *operatorSpecBuilder) newOperatorSpecProperty(operatorSpec astmodel.Type return prop } -func (b *operatorSpecBuilder) newSecretsProperty(secretsTypeName astmodel.TypeName) *astmodel.PropertyDefinition { - secretProp := astmodel.NewPropertyDefinition( - b.idFactory.CreatePropertyName(astmodel.OperatorSpecSecretsProperty, astmodel.Exported), - b.idFactory.CreateStringIdentifier(astmodel.OperatorSpecSecretsProperty, astmodel.NotExported), - secretsTypeName) - secretProp = secretProp.WithDescription("configures where to place Azure generated secrets.") - secretProp = secretProp.MakeTypeOptional() +func (b *operatorSpecBuilder) newProperty(typ astmodel.Type, propertyName string, description string) *astmodel.PropertyDefinition { + prop := astmodel.NewPropertyDefinition( + b.idFactory.CreatePropertyName(propertyName, astmodel.Exported), + b.idFactory.CreateStringIdentifier(propertyName, astmodel.NotExported), + typ) + prop = prop.WithDescription(description) + prop = prop.MakeTypeOptional() - return secretProp + return prop +} + +func (b *operatorSpecBuilder) newSecretsProperty(secretTypeName astmodel.TypeName) *astmodel.PropertyDefinition { + return b.newProperty( + secretTypeName, + astmodel.OperatorSpecSecretsProperty, + "configures where to place Azure generated secrets.") } func (b *operatorSpecBuilder) newConfigMapProperty(configMapTypeName astmodel.TypeName) *astmodel.PropertyDefinition { - configMapProp := astmodel.NewPropertyDefinition( - b.idFactory.CreatePropertyName(astmodel.OperatorSpecConfigMapsProperty, astmodel.Exported), - b.idFactory.CreateStringIdentifier(astmodel.OperatorSpecConfigMapsProperty, astmodel.NotExported), - configMapTypeName) - configMapProp = configMapProp.WithDescription("configures where to place operator written ConfigMaps.") - configMapProp = configMapProp.MakeTypeOptional() - - return configMapProp + return b.newProperty( + configMapTypeName, + astmodel.OperatorSpecConfigMapsProperty, + "configures where to place operator written ConfigMaps.") +} + +func (b *operatorSpecBuilder) newDynamicConfigMapProperty() *astmodel.PropertyDefinition { + return b.newProperty( + astmodel.DestinationExpressionCollectionType, + astmodel.OperatorSpecConfigMapExpressionsProperty, + "configures where to place operator written dynamic ConfigMaps (created with CEL expressions).") } -func (b *operatorSpecBuilder) addSecretsToOperatorSpec( +func (b *operatorSpecBuilder) newDynamicSecretProperty() *astmodel.PropertyDefinition { + return b.newProperty( + astmodel.DestinationExpressionCollectionType, + astmodel.OperatorSpecSecretExpressionsProperty, + "configures where to place operator written dynamic secrets (created with CEL expressions).") +} + +func (b *operatorSpecBuilder) addSecrets( azureGeneratedSecrets []string, ) { if len(azureGeneratedSecrets) == 0 { @@ -470,3 +498,15 @@ func (b *operatorSpecBuilder) build() (astmodel.TypeDefinition, error) { def = def.WithDescription(description) return def, nil } + +func (b *operatorSpecBuilder) addDynamicConfigMaps() { + // Add the "configMaps" property to the operator spec + configMapProp := b.newDynamicConfigMapProperty() + b.operatorSpecType = b.operatorSpecType.WithProperty(configMapProp) +} + +func (b *operatorSpecBuilder) addDynamicSecrets() { + // Add the "configMaps" property to the operator spec + configMapProp := b.newDynamicSecretProperty() + b.operatorSpecType = b.operatorSpecType.WithProperty(configMapProp) +} diff --git a/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go b/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go index 3839dd837f0..9db97505c33 100644 --- a/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go +++ b/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go @@ -8,6 +8,7 @@ package pipeline import ( "context" "fmt" + "go/token" "github.com/dave/dst" "github.com/pkg/errors" @@ -120,31 +121,21 @@ func getValidations( functions.NewValidateOwnerReferenceFunction(resource, idFactory)) } - secrets, err := getOperatorSpecSubType(defs, resource, astmodel.OperatorSpecSecretsProperty) - if err != nil { - return nil, err - } - if secrets != nil { - validations[functions.ValidationKindCreate] = append( - validations[functions.ValidationKindCreate], - NewValidateSecretDestinationsFunction(resource, idFactory)) - validations[functions.ValidationKindUpdate] = append( - validations[functions.ValidationKindUpdate], - NewValidateSecretDestinationsFunction(resource, idFactory)) - } - - configMaps, err := getOperatorSpecSubType(defs, resource, astmodel.OperatorSpecConfigMapsProperty) - if err != nil { - return nil, err - } - if configMaps != nil { - validations[functions.ValidationKindCreate] = append( - validations[functions.ValidationKindCreate], - NewValidateConfigMapDestinationsFunction(resource, idFactory)) - validations[functions.ValidationKindUpdate] = append( - validations[functions.ValidationKindUpdate], - NewValidateConfigMapDestinationsFunction(resource, idFactory)) - } + // The expectation is that every resource has an Spec.OperatorSpec.SecretExpressions and + // Spec.OperatorSpec.ConfigMapExpressions field, so we always include their validations. + // If this assumption has been violated, generating the validation function will raise an error. + validations[functions.ValidationKindCreate] = append( + validations[functions.ValidationKindCreate], + NewValidateSecretDestinationsFunction(resource, idFactory)) + validations[functions.ValidationKindUpdate] = append( + validations[functions.ValidationKindUpdate], + NewValidateSecretDestinationsFunction(resource, idFactory)) + validations[functions.ValidationKindCreate] = append( + validations[functions.ValidationKindCreate], + NewValidateConfigMapDestinationsFunction(resource, idFactory)) + validations[functions.ValidationKindUpdate] = append( + validations[functions.ValidationKindUpdate], + NewValidateConfigMapDestinationsFunction(resource, idFactory)) hasConfigMapReferencePairs, err := hasOptionalConfigMapReferencePairs(resourceDef, defs) if err != nil { @@ -192,6 +183,7 @@ func validateSecretDestinations( k.Resource(), receiverIdent, astmodel.OperatorSpecSecretsProperty, + astmodel.OperatorSpecSecretExpressionsProperty, astmodel.NewOptionalType(astmodel.SecretDestinationType), astmodel.GenRuntimeSecretsReference, "ValidateDestinations") @@ -239,6 +231,7 @@ func validateConfigMapDestinations( k.Resource(), receiverIdent, astmodel.OperatorSpecConfigMapsProperty, + astmodel.OperatorSpecConfigMapExpressionsProperty, astmodel.NewOptionalType(astmodel.ConfigMapDestinationType), astmodel.GenRuntimeConfigMapsReference, "ValidateDestinations") @@ -265,32 +258,46 @@ func validateConfigMapDestinations( // // func (account *DatabaseAccount) validateConfigMapDestinations() error { // if .Spec.OperatorSpec == nil { -// return nil -// } -// if .Spec.OperatorSpec. == nil { -// return nil -// } -// toValidate := []*{ -// account.Spec.OperatorSpec.ConfigMaps.ClientId, -// account.Spec.OperatorSpec.ConfigMaps.PrincipalId, -// ... +// return nil +// } +// +// var toValidate [] +// if .Spec.OperatorSpec. != nil { +// toValidate = []{ +// account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, +// account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, +// ... // } -// return genruntime.(toValidate) +// return .(account, toValidate, .Spec.OperatorSpec.) // } func validateOperatorSpecSliceBody( codeGenerationContext *astmodel.CodeGenerationContext, resource *astmodel.ResourceType, receiverIdent string, - operatorSpecProperty string, + property string, + expressionsProperty string, validateType astmodel.Type, validatePackage astmodel.ExternalPackageReference, validateFunctionName string, ) ([]dst.Stmt, error) { pkg := codeGenerationContext.MustGetImportedPackageName(validatePackage) - operatorSpecPropertyObj, err := getOperatorSpecSubType(codeGenerationContext, resource, operatorSpecProperty) + // operatorSpecPropertyObj and expressionsOperatorSpecPropertyObj may be nil. If BOTH are nil this method shouldn't + // have ever been called, but one can be nil. + operatorSpecPropertyObj, err := getOperatorSpecSubType(codeGenerationContext, resource, property) + if err != nil { + return nil, errors.Wrapf(err, "getting operator spec sub type for %s", property) + } + expressionsOperatorSpecPropertySlice, err := getOperatorSpecExpressionType(codeGenerationContext, resource, expressionsProperty) if err != nil { - return nil, errors.Wrapf(err, "getting operator spec sub type for %s", operatorSpecProperty) + return nil, errors.Wrapf(err, "getting operator spec sub type for %s", expressionsProperty) + } + + if operatorSpecPropertyObj == nil && expressionsOperatorSpecPropertySlice == nil { + return nil, errors.Errorf( + "can't generate method for validating OperatorSpec %s and %s if both fields don't exist", + property, + expressionsProperty) } var body []dst.Stmt @@ -302,38 +309,65 @@ func validateOperatorSpecSliceBody( operatorSpecSelector := astbuilder.Selector(specSelector, astmodel.OperatorSpecProperty) body = append(body, astbuilder.ReturnIfNil(operatorSpecSelector, astbuilder.Nil(), astbuilder.Nil())) - // if .Spec.OperatorSpec. == nil { - // return nil, nil - // } - specPropertySelector := astbuilder.Selector(operatorSpecSelector, operatorSpecProperty) - body = append(body, astbuilder.ReturnIfNil(specPropertySelector, astbuilder.Nil(), astbuilder.Nil())) - - // secrets := []{ - // account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, - // account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, - // ... - // } - validateTypeExpr, err := validateType.AsTypeExpr(codeGenerationContext) - if err != nil { - return nil, errors.Wrapf(err, "creating type expression for %s", validateType) - } + propertySelector := astbuilder.Selector(operatorSpecSelector, property) + expressionsPropertySelector := astbuilder.Selector(operatorSpecSelector, expressionsProperty) - sliceBuilder := astbuilder.NewSliceLiteralBuilder(validateTypeExpr, true) - for _, prop := range operatorSpecPropertyObj.Properties().AsSlice() { - propSelector := astbuilder.Selector(specPropertySelector, prop.PropertyName().String()) - sliceBuilder.AddElement(propSelector) - } toValidateVar := "toValidate" - body = append(body, astbuilder.ShortDeclaration(toValidateVar, sliceBuilder.Build())) - - // return genruntime.(secrets) + if operatorSpecPropertyObj != nil { + // var toValidate [] + validateTypeExpr, err := validateType.AsTypeExpr(codeGenerationContext) + if err != nil { + return nil, errors.Wrapf(err, "creating type expression for %s", validateType) + } + validateVarSliceExpr, err := astmodel.NewArrayType(validateType).AsTypeExpr(codeGenerationContext) + if err != nil { + return nil, errors.Wrapf(err, "creating type expression for %s", astmodel.NewArrayType(validateType)) + } + body = append(body, astbuilder.LocalVariableDeclaration(toValidateVar, validateVarSliceExpr, "")) + + // if .Spec.OperatorSpec. != nil { + // toValidate = []{ + // account.Spec.OperatorSpec.Secrets.PrimaryReadonlyMasterKey, + // account.Spec.OperatorSpec.Secrets.SecondaryReadonlyMasterKey, + // ... + // } + // } + + sliceBuilder := astbuilder.NewSliceLiteralBuilder(validateTypeExpr, true) + for _, prop := range operatorSpecPropertyObj.Properties().AsSlice() { + propSelector := astbuilder.Selector(propertySelector, prop.PropertyName().String()) + sliceBuilder.AddElement(propSelector) + } + body = append( + body, + astbuilder.IfNotNil( + propertySelector, + astbuilder.AssignmentStatement(dst.NewIdent(toValidateVar), token.ASSIGN, sliceBuilder.Build()))) + } + + selfParameter := dst.NewIdent(receiverIdent) + + toValidateParameter := astbuilder.Nil() + if operatorSpecPropertyObj != nil { + toValidateParameter = dst.NewIdent(toValidateVar) + } + + var expressionsToValidateParameter dst.Expr + expressionsToValidateParameter = astbuilder.Nil() + if expressionsOperatorSpecPropertySlice != nil { + expressionsToValidateParameter = expressionsPropertySelector + } + + // return .(self, toValidate, expressionsToValidate) body = append( body, astbuilder.Returns( astbuilder.CallQualifiedFunc( pkg, validateFunctionName, - dst.NewIdent(toValidateVar)))) + selfParameter, + toValidateParameter, + expressionsToValidateParameter))) return body, nil } @@ -377,6 +411,26 @@ func getOperatorSpecType(defs astmodel.ReadonlyTypeDefinitions, resource *astmod return operatorSpecType, nil } +func getOperatorSpecExpressionType(defs astmodel.ReadonlyTypeDefinitions, resource *astmodel.ResourceType, name string) (astmodel.Type, error) { + operatorSpecType, err := getOperatorSpecType(defs, resource) + if err != nil { + return nil, err + } + if operatorSpecType == nil { + // Not found, just return + return nil, nil + } + + prop, ok := operatorSpecType.Property(astmodel.PropertyName(name)) + if !ok { + // No property + return nil, nil + } + + propType := astmodel.Unwrap(prop.PropertyType()) + return propType, nil +} + func getOperatorSpecSubType(defs astmodel.ReadonlyTypeDefinitions, resource *astmodel.ResourceType, name string) (*astmodel.ObjectType, error) { operatorSpecType, err := getOperatorSpecType(defs, resource) if err != nil { @@ -387,29 +441,29 @@ func getOperatorSpecSubType(defs astmodel.ReadonlyTypeDefinitions, resource *ast return nil, nil } - secretsProp, ok := operatorSpecType.Property(astmodel.PropertyName(name)) + prop, ok := operatorSpecType.Property(astmodel.PropertyName(name)) if !ok { - // No secrets property + // No property return nil, nil } - secretsTypeName, ok := astmodel.AsInternalTypeName(secretsProp.PropertyType()) + typeName, ok := astmodel.AsInternalTypeName(prop.PropertyType()) if !ok { return nil, errors.Errorf( - "expected %s to be an astmodel.TypeName, but it was %T", + "expected %s to be an astmodel.InternalTypeName, but it was %T", name, - secretsProp.PropertyType()) + prop.PropertyType()) } - secretsDef, err := defs.GetDefinition(secretsTypeName) + def, err := defs.GetDefinition(typeName) if err != nil { return nil, err } - secretsType, ok := astmodel.AsObjectType(secretsDef.Type()) + defType, ok := astmodel.AsObjectType(def.Type()) if !ok { - panic(fmt.Sprintf("expected %s to be an astmodel.ObjectType but it was %T", secretsTypeName, secretsDef.Type())) + panic(fmt.Sprintf("expected %s to be an astmodel.ObjectType but it was %T", typeName, def.Type())) } - return secretsType, nil + return defType, nil } // hasOptionalConfigMapReferencePairs returns true if the type has optional genruntime.ConfigMapReference pairs diff --git a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddKubernetesExporter_AutomaticallyGeneratesExportedConfigMaps/person-v20200101.golden b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddKubernetesExporter_AutomaticallyGeneratesExportedConfigMaps/person-v20200101.golden index 115ad9c9b1f..ec57d966d53 100644 --- a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddKubernetesExporter_AutomaticallyGeneratesExportedConfigMaps/person-v20200101.golden +++ b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddKubernetesExporter_AutomaticallyGeneratesExportedConfigMaps/person-v20200101.golden @@ -8,6 +8,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/genericarmclient" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/go-logr/logr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -22,6 +24,26 @@ type Person struct { Status Person_STATUS `json:"status,omitempty"` } +var _ configmaps.Exporter = &Person{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (person *Person) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Person{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (person *Person) SecretDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesConfigExporter = &Person{} // ExportKubernetesConfigMaps defines a resource which can create ConfigMaps in Kubernetes. @@ -74,8 +96,14 @@ type Person_STATUS struct { // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PersonOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *PersonOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } type PersonOperatorConfigMaps struct { diff --git a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithConfiguredConfigMaps/person-v20200101.golden b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithConfiguredConfigMaps/person-v20200101.golden index 6dcbf39f477..d5c648915ab 100644 --- a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithConfiguredConfigMaps/person-v20200101.golden +++ b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithConfiguredConfigMaps/person-v20200101.golden @@ -5,6 +5,9 @@ package v20200101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -17,6 +20,26 @@ type Person struct { Status Person_STATUS `json:"status,omitempty"` } +var _ configmaps.Exporter = &Person{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (person *Person) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Person{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (person *Person) SecretDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.SecretExpressions +} + // +kubebuilder:object:root=true type PersonList struct { metav1.TypeMeta `json:",inline"` @@ -46,8 +69,14 @@ type Person_STATUS struct { // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PersonOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *PersonOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } type PersonOperatorConfigMaps struct { diff --git a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithManualConfigMaps/person-v20200101.golden b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithManualConfigMaps/person-v20200101.golden index ba3e5b32239..33ffaf21476 100644 --- a/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithManualConfigMaps/person-v20200101.golden +++ b/v2/tools/generator/internal/codegen/pipeline/testdata/TestAddOperatorSpec_AddsSpecWithManualConfigMaps/person-v20200101.golden @@ -5,6 +5,9 @@ package v20200101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -17,6 +20,26 @@ type Person struct { Status Person_STATUS `json:"status,omitempty"` } +var _ configmaps.Exporter = &Person{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (person *Person) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Person{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (person *Person) SecretDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.SecretExpressions +} + // +kubebuilder:object:root=true type PersonList struct { metav1.TypeMeta `json:",inline"` @@ -46,8 +69,14 @@ type Person_STATUS struct { // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PersonOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + // ConfigMaps: configures where to place operator written ConfigMaps. ConfigMaps *PersonOperatorConfigMaps `json:"configMaps,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` } type PersonOperatorConfigMaps struct { diff --git a/v2/tools/generator/internal/codegen/pipeline/testdata/TestGolden_AddOperatorSpec_AddsSpecWithConfiguredSecrets/person-v20200101.golden b/v2/tools/generator/internal/codegen/pipeline/testdata/TestGolden_AddOperatorSpec_AddsSpecWithConfiguredSecrets/person-v20200101.golden index 4f1ea83f027..094d2795e52 100644 --- a/v2/tools/generator/internal/codegen/pipeline/testdata/TestGolden_AddOperatorSpec_AddsSpecWithConfiguredSecrets/person-v20200101.golden +++ b/v2/tools/generator/internal/codegen/pipeline/testdata/TestGolden_AddOperatorSpec_AddsSpecWithConfiguredSecrets/person-v20200101.golden @@ -5,6 +5,9 @@ package v20200101 import ( "github.com/Azure/azure-service-operator/v2/pkg/genruntime" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -17,6 +20,26 @@ type Person struct { Status Person_STATUS `json:"status,omitempty"` } +var _ configmaps.Exporter = &Person{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (person *Person) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &Person{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (person *Person) SecretDestinationExpressions() []*core.DestinationExpression { + if person.Spec.OperatorSpec == nil { + return nil + } + return person.Spec.OperatorSpec.SecretExpressions +} + // +kubebuilder:object:root=true type PersonList struct { metav1.TypeMeta `json:",inline"` @@ -46,6 +69,12 @@ type Person_STATUS struct { // Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure type PersonOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` + // Secrets: configures where to place Azure generated secrets. Secrets *PersonOperatorSecrets `json:"secrets,omitempty"` } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure.golden index 42154fb994a..bed5c69d44a 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -308,6 +352,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -362,6 +410,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -441,6 +491,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -473,6 +535,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -537,6 +611,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure_v1api20200101.golden index effbabc41d5..20ec93c8f41 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_oneof_resource_conversion_on_arm_type_only_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,9 +206,23 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (resource *FakeResource) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(resource) @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -276,6 +321,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -330,6 +379,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -409,6 +460,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -441,6 +504,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -495,6 +570,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure.golden index 600518203e9..1e32a1fdd95 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -84,6 +86,26 @@ func (a *A) defaultAzureName() { // defaultImpl applies the code generated defaults to the A resource func (a *A) defaultImpl() { a.defaultAzureName() } +var _ configmaps.Exporter = &A{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (a *A) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if a.Spec.OperatorSpec == nil { + return nil + } + return a.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &A{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (a *A) SecretDestinationExpressions() *secrets.DestinationExpressions { + if a.Spec.OperatorSpec == nil { + return nil + } + return a.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &A{} // AzureName returns the Azure name of the resource @@ -162,7 +184,7 @@ func (a *A) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (a *A) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){a.validateResourceReferences, a.validateOwnerReference} + return []func() (admission.Warnings, error){a.validateResourceReferences, a.validateOwnerReference, a.validateSecretDestinations, a.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -180,7 +202,21 @@ func (a *A) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return a.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return a.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return a.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (a *A) validateConfigMapDestinations() (admission.Warnings, error) { + if a.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, a.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -197,6 +233,14 @@ func (a *A) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (a *A) validateSecretDestinations() (admission.Warnings, error) { + if a.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, a.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (a *A) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*A) @@ -350,6 +394,26 @@ func (b *B) defaultAzureName() { // defaultImpl applies the code generated defaults to the B resource func (b *B) defaultImpl() { b.defaultAzureName() } +var _ configmaps.Exporter = &B{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (b *B) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if b.Spec.OperatorSpec == nil { + return nil + } + return b.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &B{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (b *B) SecretDestinationExpressions() *secrets.DestinationExpressions { + if b.Spec.OperatorSpec == nil { + return nil + } + return b.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &B{} // AzureName returns the Azure name of the resource @@ -428,7 +492,7 @@ func (b *B) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (b *B) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){b.validateResourceReferences, b.validateOwnerReference} + return []func() (admission.Warnings, error){b.validateResourceReferences, b.validateOwnerReference, b.validateSecretDestinations, b.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -446,7 +510,21 @@ func (b *B) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return b.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return b.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return b.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (b *B) validateConfigMapDestinations() (admission.Warnings, error) { + if b.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, b.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -463,6 +541,14 @@ func (b *B) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (b *B) validateSecretDestinations() (admission.Warnings, error) { + if b.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, b.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (b *B) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*B) @@ -616,6 +702,26 @@ func (c *C) defaultAzureName() { // defaultImpl applies the code generated defaults to the C resource func (c *C) defaultImpl() { c.defaultAzureName() } +var _ configmaps.Exporter = &C{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (c *C) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if c.Spec.OperatorSpec == nil { + return nil + } + return c.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &C{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (c *C) SecretDestinationExpressions() *secrets.DestinationExpressions { + if c.Spec.OperatorSpec == nil { + return nil + } + return c.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &C{} // AzureName returns the Azure name of the resource @@ -694,7 +800,7 @@ func (c *C) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (c *C) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){c.validateResourceReferences, c.validateOwnerReference} + return []func() (admission.Warnings, error){c.validateResourceReferences, c.validateOwnerReference, c.validateSecretDestinations, c.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -712,9 +818,23 @@ func (c *C) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return c.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return c.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return c.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (c *C) validateConfigMapDestinations() (admission.Warnings, error) { + if c.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(nil, c.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (c *C) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(c) @@ -729,6 +849,14 @@ func (c *C) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (c *C) validateSecretDestinations() (admission.Warnings, error) { + if c.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, c.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (c *C) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*C) @@ -882,6 +1010,26 @@ func (d *D) defaultAzureName() { // defaultImpl applies the code generated defaults to the D resource func (d *D) defaultImpl() { d.defaultAzureName() } +var _ configmaps.Exporter = &D{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (d *D) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if d.Spec.OperatorSpec == nil { + return nil + } + return d.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &D{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (d *D) SecretDestinationExpressions() *secrets.DestinationExpressions { + if d.Spec.OperatorSpec == nil { + return nil + } + return d.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &D{} // AzureName returns the Azure name of the resource @@ -960,7 +1108,7 @@ func (d *D) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (d *D) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){d.validateResourceReferences, d.validateOwnerReference} + return []func() (admission.Warnings, error){d.validateResourceReferences, d.validateOwnerReference, d.validateSecretDestinations, d.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -978,7 +1126,21 @@ func (d *D) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return d.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return d.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return d.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (d *D) validateConfigMapDestinations() (admission.Warnings, error) { + if d.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, d.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -995,6 +1157,14 @@ func (d *D) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (d *D) validateSecretDestinations() (admission.Warnings, error) { + if d.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, d.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (d *D) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*D) @@ -1099,6 +1269,10 @@ type A_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1153,6 +1327,8 @@ func (a *A_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": a.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": a.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1232,6 +1408,18 @@ func (a *A_Spec) AssignProperties_From_A_Spec(source *storage.A_Spec) error { // AzureName a.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AOperatorSpec + err := operatorSpec.AssignProperties_From_AOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AOperatorSpec() to populate field OperatorSpec") + } + a.OperatorSpec = &operatorSpec + } else { + a.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1264,6 +1452,18 @@ func (a *A_Spec) AssignProperties_To_A_Spec(destination *storage.A_Spec) error { // AzureName destination.AzureName = a.AzureName + // OperatorSpec + if a.OperatorSpec != nil { + var operatorSpec storage.AOperatorSpec + err := a.OperatorSpec.AssignProperties_To_AOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = a.OriginalVersion() @@ -1331,6 +1531,10 @@ type B_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1385,6 +1589,8 @@ func (b *B_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": b.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": b.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1464,6 +1670,18 @@ func (b *B_Spec) AssignProperties_From_B_Spec(source *storage.B_Spec) error { // AzureName b.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BOperatorSpec + err := operatorSpec.AssignProperties_From_BOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BOperatorSpec() to populate field OperatorSpec") + } + b.OperatorSpec = &operatorSpec + } else { + b.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1496,6 +1714,18 @@ func (b *B_Spec) AssignProperties_To_B_Spec(destination *storage.B_Spec) error { // AzureName destination.AzureName = b.AzureName + // OperatorSpec + if b.OperatorSpec != nil { + var operatorSpec storage.BOperatorSpec + err := b.OperatorSpec.AssignProperties_To_BOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = b.OriginalVersion() @@ -1558,6 +1788,10 @@ type C_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *COperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1612,6 +1846,8 @@ func (c *C_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": c.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": c.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1691,6 +1927,18 @@ func (c *C_Spec) AssignProperties_From_C_Spec(source *storage.C_Spec) error { // AzureName c.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec COperatorSpec + err := operatorSpec.AssignProperties_From_COperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_COperatorSpec() to populate field OperatorSpec") + } + c.OperatorSpec = &operatorSpec + } else { + c.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1723,6 +1971,18 @@ func (c *C_Spec) AssignProperties_To_C_Spec(destination *storage.C_Spec) error { // AzureName destination.AzureName = c.AzureName + // OperatorSpec + if c.OperatorSpec != nil { + var operatorSpec storage.COperatorSpec + err := c.OperatorSpec.AssignProperties_To_COperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_COperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = c.OriginalVersion() @@ -1785,6 +2045,10 @@ type D_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1839,6 +2103,8 @@ func (d *D_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": d.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": d.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1918,6 +2184,18 @@ func (d *D_Spec) AssignProperties_From_D_Spec(source *storage.D_Spec) error { // AzureName d.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DOperatorSpec + err := operatorSpec.AssignProperties_From_DOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DOperatorSpec() to populate field OperatorSpec") + } + d.OperatorSpec = &operatorSpec + } else { + d.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1950,6 +2228,18 @@ func (d *D_Spec) AssignProperties_To_D_Spec(destination *storage.D_Spec) error { // AzureName destination.AzureName = d.AzureName + // OperatorSpec + if d.OperatorSpec != nil { + var operatorSpec storage.DOperatorSpec + err := d.OperatorSpec.AssignProperties_To_DOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = d.OriginalVersion() @@ -2014,6 +2304,70 @@ var a_Type_Spec_Values = map[string]A_Type_Spec{ "microsoft.azure/a": A_Type_Spec_MicrosoftAzureA, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AOperatorSpec populates our AOperatorSpec from the provided source AOperatorSpec +func (operator *AOperatorSpec) AssignProperties_From_AOperatorSpec(source *storage.AOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AOperatorSpec populates the provided destination AOperatorSpec from our AOperatorSpec +func (operator *AOperatorSpec) AssignProperties_To_AOperatorSpec(destination *storage.AOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type B_APIVersion_Spec string @@ -2034,6 +2388,70 @@ var b_Type_Spec_Values = map[string]B_Type_Spec{ "microsoft.azure/b": B_Type_Spec_MicrosoftAzureB, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BOperatorSpec populates our BOperatorSpec from the provided source BOperatorSpec +func (operator *BOperatorSpec) AssignProperties_From_BOperatorSpec(source *storage.BOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BOperatorSpec populates the provided destination BOperatorSpec from our BOperatorSpec +func (operator *BOperatorSpec) AssignProperties_To_BOperatorSpec(destination *storage.BOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type C_APIVersion_Spec string @@ -2054,6 +2472,70 @@ var c_Type_Spec_Values = map[string]C_Type_Spec{ "microsoft.azure/c": C_Type_Spec_MicrosoftAzureC, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type COperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_COperatorSpec populates our COperatorSpec from the provided source COperatorSpec +func (operator *COperatorSpec) AssignProperties_From_COperatorSpec(source *storage.COperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_COperatorSpec populates the provided destination COperatorSpec from our COperatorSpec +func (operator *COperatorSpec) AssignProperties_To_COperatorSpec(destination *storage.COperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type D_APIVersion_Spec string @@ -2074,6 +2556,70 @@ var d_Type_Spec_Values = map[string]D_Type_Spec{ "microsoft.azure/d": D_Type_Spec_MicrosoftAzureD, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DOperatorSpec populates our DOperatorSpec from the provided source DOperatorSpec +func (operator *DOperatorSpec) AssignProperties_From_DOperatorSpec(source *storage.DOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DOperatorSpec populates the provided destination DOperatorSpec from our DOperatorSpec +func (operator *DOperatorSpec) AssignProperties_To_DOperatorSpec(destination *storage.DOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&A{}, &AList{}, &B{}, &BList{}, &C{}, &CList{}, &D{}, &DList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure_v1api20200101.golden index 06212f87806..221f3c67218 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_dependent_resource_and_ownership_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -85,6 +88,26 @@ func (a *A) defaultAzureName() { // defaultImpl applies the code generated defaults to the A resource func (a *A) defaultImpl() { a.defaultAzureName() } +var _ configmaps.Exporter = &A{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (a *A) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if a.Spec.OperatorSpec == nil { + return nil + } + return a.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &A{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (a *A) SecretDestinationExpressions() []*core.DestinationExpression { + if a.Spec.OperatorSpec == nil { + return nil + } + return a.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &A{} // AzureName returns the Azure name of the resource @@ -163,7 +186,7 @@ func (a *A) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (a *A) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){a.validateResourceReferences, a.validateOwnerReference} + return []func() (admission.Warnings, error){a.validateResourceReferences, a.validateOwnerReference, a.validateSecretDestinations, a.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -181,9 +204,23 @@ func (a *A) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return a.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return a.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return a.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (a *A) validateConfigMapDestinations() (admission.Warnings, error) { + if a.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(a, nil, a.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (a *A) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(a) @@ -198,6 +235,14 @@ func (a *A) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (a *A) validateSecretDestinations() (admission.Warnings, error) { + if a.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(a, nil, a.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (a *A) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*A) @@ -328,6 +373,26 @@ func (b *B) defaultAzureName() { // defaultImpl applies the code generated defaults to the B resource func (b *B) defaultImpl() { b.defaultAzureName() } +var _ configmaps.Exporter = &B{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (b *B) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if b.Spec.OperatorSpec == nil { + return nil + } + return b.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &B{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (b *B) SecretDestinationExpressions() []*core.DestinationExpression { + if b.Spec.OperatorSpec == nil { + return nil + } + return b.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &B{} // AzureName returns the Azure name of the resource @@ -406,7 +471,7 @@ func (b *B) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (b *B) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){b.validateResourceReferences, b.validateOwnerReference} + return []func() (admission.Warnings, error){b.validateResourceReferences, b.validateOwnerReference, b.validateSecretDestinations, b.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -424,7 +489,21 @@ func (b *B) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return b.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return b.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return b.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (b *B) validateConfigMapDestinations() (admission.Warnings, error) { + if b.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(b, nil, b.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -441,6 +520,14 @@ func (b *B) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (b *B) validateSecretDestinations() (admission.Warnings, error) { + if b.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(b, nil, b.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (b *B) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*B) @@ -571,6 +658,26 @@ func (c *C) defaultAzureName() { // defaultImpl applies the code generated defaults to the C resource func (c *C) defaultImpl() { c.defaultAzureName() } +var _ configmaps.Exporter = &C{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (c *C) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if c.Spec.OperatorSpec == nil { + return nil + } + return c.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &C{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (c *C) SecretDestinationExpressions() []*core.DestinationExpression { + if c.Spec.OperatorSpec == nil { + return nil + } + return c.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &C{} // AzureName returns the Azure name of the resource @@ -649,7 +756,7 @@ func (c *C) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (c *C) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){c.validateResourceReferences, c.validateOwnerReference} + return []func() (admission.Warnings, error){c.validateResourceReferences, c.validateOwnerReference, c.validateSecretDestinations, c.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -667,7 +774,21 @@ func (c *C) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return c.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return c.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return c.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (c *C) validateConfigMapDestinations() (admission.Warnings, error) { + if c.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(c, nil, c.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -684,6 +805,14 @@ func (c *C) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (c *C) validateSecretDestinations() (admission.Warnings, error) { + if c.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(c, nil, c.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (c *C) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*C) @@ -814,6 +943,26 @@ func (d *D) defaultAzureName() { // defaultImpl applies the code generated defaults to the D resource func (d *D) defaultImpl() { d.defaultAzureName() } +var _ configmaps.Exporter = &D{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (d *D) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if d.Spec.OperatorSpec == nil { + return nil + } + return d.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &D{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (d *D) SecretDestinationExpressions() []*core.DestinationExpression { + if d.Spec.OperatorSpec == nil { + return nil + } + return d.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &D{} // AzureName returns the Azure name of the resource @@ -892,7 +1041,7 @@ func (d *D) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { // createValidations validates the creation of the resource func (d *D) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){d.validateResourceReferences, d.validateOwnerReference} + return []func() (admission.Warnings, error){d.validateResourceReferences, d.validateOwnerReference, d.validateSecretDestinations, d.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -910,9 +1059,23 @@ func (d *D) updateValidations() []func(old runtime.Object) (admission.Warnings, func(old runtime.Object) (admission.Warnings, error) { return d.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return d.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return d.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (d *D) validateConfigMapDestinations() (admission.Warnings, error) { + if d.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(d, nil, d.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (d *D) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(d) @@ -927,6 +1090,14 @@ func (d *D) validateResourceReferences() (admission.Warnings, error) { return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (d *D) validateSecretDestinations() (admission.Warnings, error) { + if d.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(d, nil, d.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (d *D) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*D) @@ -998,6 +1169,10 @@ type A_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1052,6 +1227,8 @@ func (a *A_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": a.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": a.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1131,6 +1308,18 @@ func (a *A_Spec) AssignProperties_From_A_Spec(source *storage.A_Spec) error { // AzureName a.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AOperatorSpec + err := operatorSpec.AssignProperties_From_AOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AOperatorSpec() to populate field OperatorSpec") + } + a.OperatorSpec = &operatorSpec + } else { + a.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1163,6 +1352,18 @@ func (a *A_Spec) AssignProperties_To_A_Spec(destination *storage.A_Spec) error { // AzureName destination.AzureName = a.AzureName + // OperatorSpec + if a.OperatorSpec != nil { + var operatorSpec storage.AOperatorSpec + err := a.OperatorSpec.AssignProperties_To_AOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = a.OriginalVersion() @@ -1210,6 +1411,10 @@ type B_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *BOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1264,6 +1469,8 @@ func (b *B_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": b.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": b.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1343,6 +1550,18 @@ func (b *B_Spec) AssignProperties_From_B_Spec(source *storage.B_Spec) error { // AzureName b.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec BOperatorSpec + err := operatorSpec.AssignProperties_From_BOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_BOperatorSpec() to populate field OperatorSpec") + } + b.OperatorSpec = &operatorSpec + } else { + b.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1375,6 +1594,18 @@ func (b *B_Spec) AssignProperties_To_B_Spec(destination *storage.B_Spec) error { // AzureName destination.AzureName = b.AzureName + // OperatorSpec + if b.OperatorSpec != nil { + var operatorSpec storage.BOperatorSpec + err := b.OperatorSpec.AssignProperties_To_BOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_BOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = b.OriginalVersion() @@ -1417,6 +1648,10 @@ type C_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *COperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1471,6 +1706,8 @@ func (c *C_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": c.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": c.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1550,6 +1787,18 @@ func (c *C_Spec) AssignProperties_From_C_Spec(source *storage.C_Spec) error { // AzureName c.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec COperatorSpec + err := operatorSpec.AssignProperties_From_COperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_COperatorSpec() to populate field OperatorSpec") + } + c.OperatorSpec = &operatorSpec + } else { + c.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1582,6 +1831,18 @@ func (c *C_Spec) AssignProperties_To_C_Spec(destination *storage.C_Spec) error { // AzureName destination.AzureName = c.AzureName + // OperatorSpec + if c.OperatorSpec != nil { + var operatorSpec storage.COperatorSpec + err := c.OperatorSpec.AssignProperties_To_COperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_COperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = c.OriginalVersion() @@ -1624,6 +1885,10 @@ type D_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *DOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -1678,6 +1943,8 @@ func (d *D_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerReference, armIn // Set property "AzureName": d.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": d.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -1757,6 +2024,18 @@ func (d *D_Spec) AssignProperties_From_D_Spec(source *storage.D_Spec) error { // AzureName d.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec DOperatorSpec + err := operatorSpec.AssignProperties_From_DOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_DOperatorSpec() to populate field OperatorSpec") + } + d.OperatorSpec = &operatorSpec + } else { + d.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1789,6 +2068,18 @@ func (d *D_Spec) AssignProperties_To_D_Spec(destination *storage.D_Spec) error { // AzureName destination.AzureName = d.AzureName + // OperatorSpec + if d.OperatorSpec != nil { + var operatorSpec storage.DOperatorSpec + err := d.OperatorSpec.AssignProperties_To_DOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_DOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = d.OriginalVersion() @@ -1843,6 +2134,110 @@ var a_Type_Spec_Values = map[string]A_Type_Spec{ "microsoft.azure/a": A_Type_Spec_MicrosoftAzureA, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AOperatorSpec populates our AOperatorSpec from the provided source AOperatorSpec +func (operator *AOperatorSpec) AssignProperties_From_AOperatorSpec(source *storage.AOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AOperatorSpec populates the provided destination AOperatorSpec from our AOperatorSpec +func (operator *AOperatorSpec) AssignProperties_To_AOperatorSpec(destination *storage.AOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type B_APIVersion_Spec string @@ -1863,6 +2258,110 @@ var b_Type_Spec_Values = map[string]B_Type_Spec{ "microsoft.azure/b": B_Type_Spec_MicrosoftAzureB, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type BOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_BOperatorSpec populates our BOperatorSpec from the provided source BOperatorSpec +func (operator *BOperatorSpec) AssignProperties_From_BOperatorSpec(source *storage.BOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_BOperatorSpec populates the provided destination BOperatorSpec from our BOperatorSpec +func (operator *BOperatorSpec) AssignProperties_To_BOperatorSpec(destination *storage.BOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type C_APIVersion_Spec string @@ -1883,6 +2382,110 @@ var c_Type_Spec_Values = map[string]C_Type_Spec{ "microsoft.azure/c": C_Type_Spec_MicrosoftAzureC, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type COperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_COperatorSpec populates our COperatorSpec from the provided source COperatorSpec +func (operator *COperatorSpec) AssignProperties_From_COperatorSpec(source *storage.COperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_COperatorSpec populates the provided destination COperatorSpec from our COperatorSpec +func (operator *COperatorSpec) AssignProperties_To_COperatorSpec(destination *storage.COperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // +kubebuilder:validation:Enum={"2020-06-01"} type D_APIVersion_Spec string @@ -1903,6 +2506,110 @@ var d_Type_Spec_Values = map[string]D_Type_Spec{ "microsoft.azure/d": D_Type_Spec_MicrosoftAzureD, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type DOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_DOperatorSpec populates our DOperatorSpec from the provided source DOperatorSpec +func (operator *DOperatorSpec) AssignProperties_From_DOperatorSpec(source *storage.DOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_DOperatorSpec populates the provided destination DOperatorSpec from our DOperatorSpec +func (operator *DOperatorSpec) AssignProperties_To_DOperatorSpec(destination *storage.DOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&A{}, &AList{}, &B{}, &BList{}, &C{}, &CList{}, &D{}, &DList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure.golden index 337176b2c50..273b9a8627d 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -311,6 +355,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -378,6 +426,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -468,6 +518,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -512,6 +574,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -596,6 +670,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/FakeResourceProperties type FakeResourceProperties struct { // NsgMapReferences: A map of NSG IDs of the form diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure_v1api20200101.golden index 28c44da8a6a..87d00781572 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_id_resource_reference_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -276,6 +321,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -343,6 +392,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -433,6 +484,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -477,6 +540,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -543,6 +618,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/FakeResourceProperties type FakeResourceProperties struct { // NsgMapReferences: A map of NSG IDs of the form diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure.golden index 014d6a145f6..158da94a3cd 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -311,6 +355,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -378,6 +426,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -468,6 +518,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -512,6 +574,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -594,6 +668,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/FakeResourceProperties type FakeResourceProperties struct { // OptionalVNetReference: A string of the form diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure_v1api20200101.golden index 39fda2fedfd..a0df1477ff3 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_required_and_optional_resource_references_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -276,6 +321,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -343,6 +392,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -433,6 +484,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -477,6 +540,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -543,6 +618,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/FakeResourceProperties type FakeResourceProperties struct { // OptionalVNetReference: A string of the form diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure.golden index 59653a35ecb..fa6d1e8a7a0 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -337,6 +381,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -517,6 +565,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -721,6 +771,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -878,6 +940,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -964,6 +1038,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { Name *string `json:"name,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure_v1api20200101.golden index dcc1e641189..15f346c5b11 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_array_properties_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -283,6 +328,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -463,6 +512,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -667,6 +718,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -824,6 +887,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -895,6 +970,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { Name *string `json:"name,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure.golden index 005d674c997..8f53ee0a277 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -336,6 +380,10 @@ type FakeResource_Spec struct { // Foo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo Foo *Foo `json:"foo,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // OptionalFoo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo OptionalFoo *Foo `json:"optionalFoo,omitempty"` @@ -440,6 +488,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.Foo = &foo } + // no assignment for property "OperatorSpec" + // Set property "OptionalFoo": if typedInput.OptionalFoo != nil { var optionalFoo1 Foo @@ -551,6 +601,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.Foo = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalFoo if source.OptionalFoo != nil { var optionalFoo Foo @@ -615,6 +677,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.Foo = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalFoo if resource.OptionalFoo != nil { var optionalFoo storage.Foo @@ -712,6 +786,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { Name *string `json:"name,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure_v1api20200101.golden index 936e7d321ff..b96d7f504a3 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_complex_properties_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -281,6 +326,10 @@ type FakeResource_Spec struct { // Foo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo Foo *Foo `json:"foo,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // OptionalFoo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo OptionalFoo *Foo `json:"optionalFoo,omitempty"` @@ -385,6 +434,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.Foo = &foo } + // no assignment for property "OperatorSpec" + // Set property "OptionalFoo": if typedInput.OptionalFoo != nil { var optionalFoo1 Foo @@ -496,6 +547,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.Foo = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalFoo if source.OptionalFoo != nil { var optionalFoo Foo @@ -560,6 +623,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.Foo = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalFoo if resource.OptionalFoo != nil { var optionalFoo storage.Foo @@ -642,6 +717,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { Name *string `json:"name,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure.golden index 34c870604d1..6e388d2d752 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -87,6 +89,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +187,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +205,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +236,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -317,7 +361,11 @@ type FakeResource_Spec struct { // +kubebuilder:validation:Required MandatoryJson *v1.JSON `json:"mandatoryJson,omitempty"` - OptionalJson *v1.JSON `json:"optionalJson,omitempty"` + + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + OptionalJson *v1.JSON `json:"optionalJson,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -407,6 +455,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.MandatoryJson = &mandatoryJson } + // no assignment for property "OperatorSpec" + // Set property "OptionalJson": if typedInput.OptionalJson != nil { optionalJson := *(*typedInput.OptionalJson).DeepCopy() @@ -513,6 +563,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.MandatoryJson = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalJson if source.OptionalJson != nil { optionalJson := *source.OptionalJson.DeepCopy() @@ -574,6 +636,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.MandatoryJson = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalJson if resource.OptionalJson != nil { optionalJson := *resource.OptionalJson.DeepCopy() @@ -646,6 +720,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure_v1api20200101.golden index 1223ee2f8de..6a59bf347d8 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_json_fields_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -88,6 +91,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -166,7 +189,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -184,9 +207,23 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (resource *FakeResource) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(resource) @@ -201,6 +238,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -282,7 +327,11 @@ type FakeResource_Spec struct { // +kubebuilder:validation:Required MandatoryJson *v1.JSON `json:"mandatoryJson,omitempty"` - OptionalJson *v1.JSON `json:"optionalJson,omitempty"` + + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + OptionalJson *v1.JSON `json:"optionalJson,omitempty"` // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also @@ -372,6 +421,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.MandatoryJson = &mandatoryJson } + // no assignment for property "OperatorSpec" + // Set property "OptionalJson": if typedInput.OptionalJson != nil { optionalJson := *(*typedInput.OptionalJson).DeepCopy() @@ -478,6 +529,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.MandatoryJson = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalJson if source.OptionalJson != nil { optionalJson := *source.OptionalJson.DeepCopy() @@ -539,6 +602,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.MandatoryJson = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalJson if resource.OptionalJson != nil { optionalJson := *resource.OptionalJson.DeepCopy() @@ -601,6 +676,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure.golden index ad4e527eabf..733471f00ef 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -341,6 +385,10 @@ type FakeResource_Spec struct { MapOfMapsOfMapsOfStrings map[string]map[string]map[string]string `json:"mapOfMapsOfMapsOfStrings,omitempty"` MapOfStrings map[string]string `json:"mapOfStrings,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -615,6 +663,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -845,6 +895,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // MapOfStrings resource.MapOfStrings = genruntime.CloneMapOfStringToString(source.MapOfStrings) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -1028,6 +1090,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // MapOfStrings destination.MapOfStrings = genruntime.CloneMapOfStringToString(resource.MapOfStrings) + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -1114,6 +1188,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { FooName *string `json:"fooName,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure_v1api20200101.golden index 60cf2e6218c..fbd27684d02 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_map_properties_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -285,6 +330,10 @@ type FakeResource_Spec struct { MapOfMapsOfMapsOfStrings map[string]map[string]map[string]string `json:"mapOfMapsOfMapsOfStrings,omitempty"` MapOfStrings map[string]string `json:"mapOfStrings,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -559,6 +608,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn } } + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -789,6 +840,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // MapOfStrings resource.MapOfStrings = genruntime.CloneMapOfStringToString(source.MapOfStrings) + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -972,6 +1035,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // MapOfStrings destination.MapOfStrings = genruntime.CloneMapOfStringToString(resource.MapOfStrings) + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -1043,6 +1118,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { FooName *string `json:"fooName,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure.golden index 42154fb994a..bed5c69d44a 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -308,6 +352,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -362,6 +410,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -441,6 +491,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -473,6 +535,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -537,6 +611,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure_v1api20200101.golden index effbabc41d5..20ec93c8f41 100644 --- a/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/ArmResource/Arm_test_simple_resource_renders_spec_azure_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,9 +206,23 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (resource *FakeResource) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(resource) @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -276,6 +321,10 @@ type FakeResource_Spec struct { // doesn't have to be. AzureName string `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -330,6 +379,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -409,6 +460,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc // AzureName resource.AzureName = source.AzureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -441,6 +504,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina // AzureName destination.AzureName = resource.AzureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -495,6 +570,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&FakeResource{}, &FakeResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource.golden b/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource.golden index 8234a9eebb4..f16dc545cff 100644 --- a/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource.golden +++ b/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -164,7 +186,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -343,6 +387,10 @@ type FakeResource_Spec struct { // Foo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo Foo *Foo `json:"foo,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // OptionalFoo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo OptionalFoo *Foo `json:"optionalFoo,omitempty"` @@ -447,6 +495,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.Foo = &foo } + // no assignment for property "OperatorSpec" + // Set property "OptionalFoo": if typedInput.OptionalFoo != nil { var optionalFoo1 Foo @@ -558,6 +608,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.Foo = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalFoo if source.OptionalFoo != nil { var optionalFoo Foo @@ -622,6 +684,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.Foo = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalFoo if resource.OptionalFoo != nil { var optionalFoo storage.Foo @@ -787,6 +861,70 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { EmbeddedTestType `json:",inline,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource_v1api20200101.golden index 8e3f5c39048..abef8fa7f60 100644 --- a/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/EmbeddedTypes/Embedded_type_simple_resource_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *FakeResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the FakeResource resource func (resource *FakeResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &FakeResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *FakeResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &FakeResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *FakeResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &FakeResource{} // AzureName returns the Azure name of the resource @@ -165,7 +188,7 @@ func (resource *FakeResource) ValidateUpdate(old runtime.Object) (admission.Warn // createValidations validates the creation of the resource func (resource *FakeResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,7 +206,21 @@ func (resource *FakeResource) updateValidations() []func(old runtime.Object) (ad func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *FakeResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -200,6 +237,14 @@ func (resource *FakeResource) validateResourceReferences() (admission.Warnings, return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *FakeResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *FakeResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*FakeResource) @@ -283,6 +328,10 @@ type FakeResource_Spec struct { // Foo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo Foo *Foo `json:"foo,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *FakeResourceOperatorSpec `json:"operatorSpec,omitempty"` + // OptionalFoo: Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo OptionalFoo *Foo `json:"optionalFoo,omitempty"` @@ -387,6 +436,8 @@ func (resource *FakeResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwn resource.Foo = &foo } + // no assignment for property "OperatorSpec" + // Set property "OptionalFoo": if typedInput.OptionalFoo != nil { var optionalFoo1 Foo @@ -498,6 +549,18 @@ func (resource *FakeResource_Spec) AssignProperties_From_FakeResource_Spec(sourc resource.Foo = nil } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec FakeResourceOperatorSpec + err := operatorSpec.AssignProperties_From_FakeResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // OptionalFoo if source.OptionalFoo != nil { var optionalFoo Foo @@ -562,6 +625,18 @@ func (resource *FakeResource_Spec) AssignProperties_To_FakeResource_Spec(destina destination.Foo = nil } + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.FakeResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_FakeResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_FakeResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OptionalFoo if resource.OptionalFoo != nil { var optionalFoo storage.Foo @@ -711,6 +786,110 @@ var fakeResource_Type_Spec_Values = map[string]FakeResource_Type_Spec{ "microsoft.azure/fakeresource": FakeResource_Type_Spec_MicrosoftAzureFakeResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type FakeResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_FakeResourceOperatorSpec populates our FakeResourceOperatorSpec from the provided source FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_From_FakeResourceOperatorSpec(source *storage.FakeResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_FakeResourceOperatorSpec populates the provided destination FakeResourceOperatorSpec from our FakeResourceOperatorSpec +func (operator *FakeResourceOperatorSpec) AssignProperties_To_FakeResourceOperatorSpec(destination *storage.FakeResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + // Generated from: https://test.test/schemas/2020-01-01/test.json#/definitions/Foo type Foo struct { EmbeddedTestType `json:",inline,omitempty"` diff --git a/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name.golden b/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name.golden index 4a86b74fa25..97f08474eec 100644 --- a/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name.golden +++ b/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -86,6 +88,26 @@ func (resource *AResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the AResource resource func (resource *AResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &AResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *AResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *AResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AResource{} // AzureName returns the Azure name of the resource (string representation of github.com/Azure/azure-service-operator/testing/test/v1api20200101/AResource_Name_Spec) @@ -164,7 +186,7 @@ func (resource *AResource) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (resource *AResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -182,7 +204,21 @@ func (resource *AResource) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *AResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -199,6 +235,14 @@ func (resource *AResource) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *AResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *AResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AResource) @@ -308,6 +352,10 @@ type AResource_Spec struct { // doesn't have to be. AzureName AResource_Name_Spec `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -362,6 +410,8 @@ func (resource *AResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -442,6 +492,18 @@ func (resource *AResource_Spec) AssignProperties_From_AResource_Spec(source *sto azureName := genruntime.ToEnum(string(source.AzureName), aResource_Name_Spec_Values) resource.AzureName = azureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AResourceOperatorSpec + err := operatorSpec.AssignProperties_From_AResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -475,6 +537,18 @@ func (resource *AResource_Spec) AssignProperties_To_AResource_Spec(destination * azureName := genruntime.ToEnum(string(resource.AzureName), aResource_Name_Spec_Values) destination.AzureName = azureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.AResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_AResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -557,6 +631,70 @@ var aResource_Type_Spec_Values = map[string]AResource_Type_Spec{ "microsoft.azure/aresource": AResource_Type_Spec_MicrosoftAzureAResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AResourceOperatorSpec populates our AResourceOperatorSpec from the provided source AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_From_AResourceOperatorSpec(source *storage.AResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AResourceOperatorSpec populates the provided destination AResourceOperatorSpec from our AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_To_AResourceOperatorSpec(destination *storage.AResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AResource{}, &AResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name_v1api20200101.golden index 4d53f17502f..a4b19ea9e31 100644 --- a/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/EnumNames/Multi_valued_enum_name_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -87,6 +90,26 @@ func (resource *AResource) defaultAzureName() { // defaultImpl applies the code generated defaults to the AResource resource func (resource *AResource) defaultImpl() { resource.defaultAzureName() } +var _ configmaps.Exporter = &AResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *AResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *AResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AResource{} // AzureName returns the Azure name of the resource (string representation of github.com/Azure/azure-service-operator/testing/test/v1api20200101/AResource_Name_Spec) @@ -165,7 +188,7 @@ func (resource *AResource) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (resource *AResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -183,9 +206,23 @@ func (resource *AResource) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *AResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (resource *AResource) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(resource) @@ -200,6 +237,14 @@ func (resource *AResource) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *AResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *AResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AResource) @@ -276,6 +321,10 @@ type AResource_Spec struct { // doesn't have to be. AzureName AResource_Name_Spec `json:"azureName,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -330,6 +379,8 @@ func (resource *AResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR // Set property "AzureName": resource.SetAzureName(genruntime.ExtractKubernetesResourceNameFromARMName(typedInput.Name)) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -410,6 +461,18 @@ func (resource *AResource_Spec) AssignProperties_From_AResource_Spec(source *sto azureName := genruntime.ToEnum(string(source.AzureName), aResource_Name_Spec_Values) resource.AzureName = azureName + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AResourceOperatorSpec + err := operatorSpec.AssignProperties_From_AResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -443,6 +506,18 @@ func (resource *AResource_Spec) AssignProperties_To_AResource_Spec(destination * azureName := genruntime.ToEnum(string(resource.AzureName), aResource_Name_Spec_Values) destination.AzureName = azureName + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.AResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_AResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -515,6 +590,110 @@ var aResource_Type_Spec_Values = map[string]AResource_Type_Spec{ "microsoft.azure/aresource": AResource_Type_Spec_MicrosoftAzureAResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AResourceOperatorSpec populates our AResourceOperatorSpec from the provided source AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_From_AResourceOperatorSpec(source *storage.AResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AResourceOperatorSpec populates the provided destination AResourceOperatorSpec from our AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_To_AResourceOperatorSpec(destination *storage.AResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AResource{}, &AResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name.golden b/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name.golden index 11f4865e975..02a2c0c33c2 100644 --- a/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name.golden +++ b/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name.golden @@ -9,6 +9,8 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -79,6 +81,26 @@ func (resource *AResource) Default() { // defaultImpl applies the code generated defaults to the AResource resource func (resource *AResource) defaultImpl() {} +var _ configmaps.Exporter = &AResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *AResource) ConfigMapDestinationExpressions() *configmaps.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *AResource) SecretDestinationExpressions() *secrets.DestinationExpressions { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AResource{} // AzureName returns the Azure name of the resource (always "onlyonevalue") @@ -157,7 +179,7 @@ func (resource *AResource) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (resource *AResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -175,7 +197,21 @@ func (resource *AResource) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, + } +} + +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *AResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil } + return configmaps.ValidateDestinations(nil, resource.Spec.OperatorSpec.ConfigMapExpressions) } // validateOwnerReference validates the owner field @@ -192,6 +228,14 @@ func (resource *AResource) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *AResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *AResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AResource) @@ -297,6 +341,10 @@ type AResource_Spec struct { // +kubebuilder:validation:Required APIVersion AResource_APIVersion_Spec `json:"apiVersion,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -348,6 +396,8 @@ func (resource *AResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR temp = string(typedInput.APIVersion) resource.APIVersion = AResource_APIVersion_Spec(temp) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -424,6 +474,18 @@ func (resource *AResource_Spec) AssignProperties_From_AResource_Spec(source *sto resource.APIVersion = "" } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AResourceOperatorSpec + err := operatorSpec.AssignProperties_From_AResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -453,6 +515,18 @@ func (resource *AResource_Spec) AssignProperties_To_AResource_Spec(destination * apiVersion := string(resource.APIVersion) destination.APIVersion = &apiVersion + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.AResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_AResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -514,6 +588,70 @@ var aResource_Type_Spec_Values = map[string]AResource_Type_Spec{ "microsoft.azure/aresource": AResource_Type_Spec_MicrosoftAzureAResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions *configmaps.DestinationExpressions `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions *secrets.DestinationExpressions `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AResourceOperatorSpec populates our AResourceOperatorSpec from the provided source AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_From_AResourceOperatorSpec(source *storage.AResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpression := *source.ConfigMapExpressions.DeepCopy() + operator.ConfigMapExpressions = &configMapExpression + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpression := *source.SecretExpressions.DeepCopy() + operator.SecretExpressions = &secretExpression + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AResourceOperatorSpec populates the provided destination AResourceOperatorSpec from our AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_To_AResourceOperatorSpec(destination *storage.AResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpression := *operator.ConfigMapExpressions.DeepCopy() + destination.ConfigMapExpressions = &configMapExpression + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpression := *operator.SecretExpressions.DeepCopy() + destination.SecretExpressions = &secretExpression + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AResource{}, &AResourceList{}) } diff --git a/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name_v1api20200101.golden b/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name_v1api20200101.golden index 9e8d45b16fe..bb185338d7e 100644 --- a/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name_v1api20200101.golden +++ b/v2/tools/generator/internal/codegen/testdata/EnumNames/Single_valued_enum_name_v1api20200101.golden @@ -10,6 +10,9 @@ import ( "github.com/Azure/azure-service-operator/v2/internal/reflecthelpers" "github.com/Azure/azure-service-operator/v2/pkg/genruntime" "github.com/Azure/azure-service-operator/v2/pkg/genruntime/conditions" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/core" + "github.com/Azure/azure-service-operator/v2/pkg/genruntime/secrets" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -80,6 +83,26 @@ func (resource *AResource) Default() { // defaultImpl applies the code generated defaults to the AResource resource func (resource *AResource) defaultImpl() {} +var _ configmaps.Exporter = &AResource{} + +// ConfigMapDestinationExpressions returns the Spec.OperatorSpec.ConfigMapExpressions property +func (resource *AResource) ConfigMapDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.ConfigMapExpressions +} + +var _ secrets.Exporter = &AResource{} + +// SecretDestinationExpressions returns the Spec.OperatorSpec.SecretExpressions property +func (resource *AResource) SecretDestinationExpressions() []*core.DestinationExpression { + if resource.Spec.OperatorSpec == nil { + return nil + } + return resource.Spec.OperatorSpec.SecretExpressions +} + var _ genruntime.KubernetesResource = &AResource{} // AzureName returns the Azure name of the resource (always "onlyonevalue") @@ -158,7 +181,7 @@ func (resource *AResource) ValidateUpdate(old runtime.Object) (admission.Warning // createValidations validates the creation of the resource func (resource *AResource) createValidations() []func() (admission.Warnings, error) { - return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference} + return []func() (admission.Warnings, error){resource.validateResourceReferences, resource.validateOwnerReference, resource.validateSecretDestinations, resource.validateConfigMapDestinations} } // deleteValidations validates the deletion of the resource @@ -176,9 +199,23 @@ func (resource *AResource) updateValidations() []func(old runtime.Object) (admis func(old runtime.Object) (admission.Warnings, error) { return resource.validateOwnerReference() }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateSecretDestinations() + }, + func(old runtime.Object) (admission.Warnings, error) { + return resource.validateConfigMapDestinations() + }, } } +// validateConfigMapDestinations validates there are no colliding genruntime.ConfigMapDestinations +func (resource *AResource) validateConfigMapDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return configmaps.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.ConfigMapExpressions) +} + // validateOwnerReference validates the owner field func (resource *AResource) validateOwnerReference() (admission.Warnings, error) { return genruntime.ValidateOwner(resource) @@ -193,6 +230,14 @@ func (resource *AResource) validateResourceReferences() (admission.Warnings, err return genruntime.ValidateResourceReferences(refs) } +// validateSecretDestinations validates there are no colliding genruntime.SecretDestination's +func (resource *AResource) validateSecretDestinations() (admission.Warnings, error) { + if resource.Spec.OperatorSpec == nil { + return nil, nil + } + return secrets.ValidateDestinations(resource, nil, resource.Spec.OperatorSpec.SecretExpressions) +} + // validateWriteOnceProperties validates all WriteOnce properties func (resource *AResource) validateWriteOnceProperties(old runtime.Object) (admission.Warnings, error) { oldObj, ok := old.(*AResource) @@ -265,6 +310,10 @@ type AResource_Spec struct { // +kubebuilder:validation:Required APIVersion AResource_APIVersion_Spec `json:"apiVersion,omitempty"` + // OperatorSpec: The specification for configuring operator behavior. This field is interpreted by the operator and not + // passed directly to Azure + OperatorSpec *AResourceOperatorSpec `json:"operatorSpec,omitempty"` + // +kubebuilder:validation:Required // Owner: The owner of the resource. The owner controls where the resource goes when it is deployed. The owner also // controls the resources lifecycle. When the owner is deleted the resource will also be deleted. Owner is expected to be a @@ -316,6 +365,8 @@ func (resource *AResource_Spec) PopulateFromARM(owner genruntime.ArbitraryOwnerR temp = string(typedInput.APIVersion) resource.APIVersion = AResource_APIVersion_Spec(temp) + // no assignment for property "OperatorSpec" + // Set property "Owner": resource.Owner = &genruntime.KnownResourceReference{ Name: owner.Name, @@ -392,6 +443,18 @@ func (resource *AResource_Spec) AssignProperties_From_AResource_Spec(source *sto resource.APIVersion = "" } + // OperatorSpec + if source.OperatorSpec != nil { + var operatorSpec AResourceOperatorSpec + err := operatorSpec.AssignProperties_From_AResourceOperatorSpec(source.OperatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_From_AResourceOperatorSpec() to populate field OperatorSpec") + } + resource.OperatorSpec = &operatorSpec + } else { + resource.OperatorSpec = nil + } + // Owner if source.Owner != nil { owner := source.Owner.Copy() @@ -421,6 +484,18 @@ func (resource *AResource_Spec) AssignProperties_To_AResource_Spec(destination * apiVersion := string(resource.APIVersion) destination.APIVersion = &apiVersion + // OperatorSpec + if resource.OperatorSpec != nil { + var operatorSpec storage.AResourceOperatorSpec + err := resource.OperatorSpec.AssignProperties_To_AResourceOperatorSpec(&operatorSpec) + if err != nil { + return errors.Wrap(err, "calling AssignProperties_To_AResourceOperatorSpec() to populate field OperatorSpec") + } + destination.OperatorSpec = &operatorSpec + } else { + destination.OperatorSpec = nil + } + // OriginalVersion destination.OriginalVersion = resource.OriginalVersion() @@ -472,6 +547,110 @@ var aResource_Type_Spec_Values = map[string]AResource_Type_Spec{ "microsoft.azure/aresource": AResource_Type_Spec_MicrosoftAzureAResource, } +// Details for configuring operator behavior. Fields in this struct are interpreted by the operator directly rather than being passed to Azure +type AResourceOperatorSpec struct { + // ConfigMapExpressions: configures where to place operator written dynamic ConfigMaps (created with CEL expressions). + ConfigMapExpressions []*core.DestinationExpression `json:"configMapExpressions,omitempty"` + + // SecretExpressions: configures where to place operator written dynamic secrets (created with CEL expressions). + SecretExpressions []*core.DestinationExpression `json:"secretExpressions,omitempty"` +} + +// AssignProperties_From_AResourceOperatorSpec populates our AResourceOperatorSpec from the provided source AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_From_AResourceOperatorSpec(source *storage.AResourceOperatorSpec) error { + + // ConfigMapExpressions + if source.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(source.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range source.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + operator.ConfigMapExpressions = configMapExpressionList + } else { + operator.ConfigMapExpressions = nil + } + + // SecretExpressions + if source.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(source.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range source.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + operator.SecretExpressions = secretExpressionList + } else { + operator.SecretExpressions = nil + } + + // No error + return nil +} + +// AssignProperties_To_AResourceOperatorSpec populates the provided destination AResourceOperatorSpec from our AResourceOperatorSpec +func (operator *AResourceOperatorSpec) AssignProperties_To_AResourceOperatorSpec(destination *storage.AResourceOperatorSpec) error { + // Create a new property bag + propertyBag := genruntime.NewPropertyBag() + + // ConfigMapExpressions + if operator.ConfigMapExpressions != nil { + configMapExpressionList := make([]*core.DestinationExpression, len(operator.ConfigMapExpressions)) + for configMapExpressionIndex, configMapExpressionItem := range operator.ConfigMapExpressions { + // Shadow the loop variable to avoid aliasing + configMapExpressionItem := configMapExpressionItem + if configMapExpressionItem != nil { + configMapExpression := *configMapExpressionItem.DeepCopy() + configMapExpressionList[configMapExpressionIndex] = &configMapExpression + } else { + configMapExpressionList[configMapExpressionIndex] = nil + } + } + destination.ConfigMapExpressions = configMapExpressionList + } else { + destination.ConfigMapExpressions = nil + } + + // SecretExpressions + if operator.SecretExpressions != nil { + secretExpressionList := make([]*core.DestinationExpression, len(operator.SecretExpressions)) + for secretExpressionIndex, secretExpressionItem := range operator.SecretExpressions { + // Shadow the loop variable to avoid aliasing + secretExpressionItem := secretExpressionItem + if secretExpressionItem != nil { + secretExpression := *secretExpressionItem.DeepCopy() + secretExpressionList[secretExpressionIndex] = &secretExpression + } else { + secretExpressionList[secretExpressionIndex] = nil + } + } + destination.SecretExpressions = secretExpressionList + } else { + destination.SecretExpressions = nil + } + + // Update the property bag + if len(propertyBag) > 0 { + destination.PropertyBag = propertyBag + } else { + destination.PropertyBag = nil + } + + // No error + return nil +} + func init() { SchemeBuilder.Register(&AResource{}, &AResourceList{}) } diff --git a/v2/tools/generator/internal/conversions/property_conversions.go b/v2/tools/generator/internal/conversions/property_conversions.go index e337b44f95d..5c82f8b1bf9 100644 --- a/v2/tools/generator/internal/conversions/property_conversions.go +++ b/v2/tools/generator/internal/conversions/property_conversions.go @@ -87,6 +87,7 @@ func init() { copyKnownType(astmodel.SecretDestinationType, "Copy", returnsValue), copyKnownType(astmodel.ConfigMapReferenceType, "Copy", returnsValue), copyKnownType(astmodel.ConfigMapDestinationType, "Copy", returnsValue), + copyKnownType(astmodel.DestinationExpressionType, "DeepCopy", returnsReference), copyKnownType(astmodel.ArbitraryOwnerReference, "Copy", returnsValue), copyKnownType(astmodel.ConditionType, "Copy", returnsValue), copyKnownType(astmodel.JSONType, "DeepCopy", returnsReference), diff --git a/v2/tools/generator/internal/functions/dynamic_exports.go b/v2/tools/generator/internal/functions/dynamic_exports.go new file mode 100644 index 00000000000..ccccaffed91 --- /dev/null +++ b/v2/tools/generator/internal/functions/dynamic_exports.go @@ -0,0 +1,154 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT license. + */ + +package functions + +import ( + "fmt" + "strings" + + "github.com/dave/dst" + "github.com/pkg/errors" + + "github.com/Azure/azure-service-operator/v2/tools/generator/internal/astbuilder" + "github.com/Azure/azure-service-operator/v2/tools/generator/internal/astmodel" +) + +// PropertyExporter is a helper that helps build functions that just export a struct property. +// For example a function GetFoo that just returned s.foo. +type PropertyExporter struct { + resourceName astmodel.InternalTypeName + resource *astmodel.ResourceType + idFactory astmodel.IdentifierFactory + + nilChecks [][]string + propertyPath []string + functionName string + exportType astmodel.Type + interfaceName astmodel.ExternalTypeName +} + +func newPropertyExporterInterface( + resourceName astmodel.InternalTypeName, + resource *astmodel.ResourceType, + idFactory astmodel.IdentifierFactory, + nilChecks [][]string, + propertyPath []string, + functionName string, + exportType astmodel.Type, + interfaceName astmodel.ExternalTypeName, +) *PropertyExporter { + return &PropertyExporter{ + resourceName: resourceName, + resource: resource, + idFactory: idFactory, + + nilChecks: nilChecks, + propertyPath: propertyPath, + functionName: functionName, + exportType: exportType, + interfaceName: interfaceName, + } +} + +func NewConfigMapExporterInterface( + resourceName astmodel.InternalTypeName, + resource *astmodel.ResourceType, + idFactory astmodel.IdentifierFactory, +) *PropertyExporter { + return newPropertyExporterInterface( + resourceName, + resource, + idFactory, + [][]string{{"Spec", astmodel.OperatorSpecProperty}}, + []string{"Spec", astmodel.OperatorSpecProperty, astmodel.OperatorSpecConfigMapExpressionsProperty}, + "ConfigMapDestinationExpressions", + astmodel.DestinationExpressionCollectionType, + astmodel.ConfigMapExporterType) +} + +func NewSecretsExporterInterface( + resourceName astmodel.InternalTypeName, + resource *astmodel.ResourceType, + idFactory astmodel.IdentifierFactory, +) *PropertyExporter { + return newPropertyExporterInterface( + resourceName, + resource, + idFactory, + [][]string{{"Spec", astmodel.OperatorSpecProperty}}, + []string{"Spec", astmodel.OperatorSpecProperty, astmodel.OperatorSpecSecretExpressionsProperty}, + "SecretDestinationExpressions", + astmodel.DestinationExpressionCollectionType, + astmodel.SecretExporterType) +} + +func (d *PropertyExporter) ToInterfaceImplementation() *astmodel.InterfaceImplementation { + funcs := []astmodel.Function{ + NewResourceFunction( + d.functionName, + d.resource, + d.idFactory, + d.getPropertyFunction, + astmodel.NewPackageReferenceSet()), + } + + return astmodel.NewInterfaceImplementation( + d.interfaceName, + funcs...) +} + +// getPropertyFunction returns a function declaration for getting the property. +// +// func (r *) () { +// +// +// return +// } +func (d *PropertyExporter) getPropertyFunction( + f *ResourceFunction, + genContext *astmodel.CodeGenerationContext, + receiver astmodel.TypeName, + _ string, +) (*dst.FuncDecl, error) { + receiverIdent := f.IdFactory().CreateReceiver(receiver.Name()) + receiverType := astmodel.NewOptionalType(receiver) + receiverTypeExpr, err := receiverType.AsTypeExpr(genContext) + if err != nil { + return nil, errors.Wrap(err, "creating receiver type expression") + } + + nilChecks := make([]dst.Stmt, 0, len(d.nilChecks)) + for _, check := range d.nilChecks { + nilChecks = append( + nilChecks, + astbuilder.ReturnIfNil( + astbuilder.Selector( + dst.NewIdent(receiverIdent), check...), astbuilder.Nil(), + ), + ) + } + + ret := astbuilder.Returns(astbuilder.Selector(dst.NewIdent(receiverIdent), d.propertyPath...)) + + fn := &astbuilder.FuncDetails{ + ReceiverIdent: receiverIdent, + ReceiverType: receiverTypeExpr, + Name: d.functionName, + Body: astbuilder.Statements( + nilChecks, + ret), + } + + exportTypeExpr, err := d.exportType.AsTypeExpr(genContext) + if err != nil { + return nil, errors.Wrap(err, "creating return type expression") + } + + fn.AddReturn(exportTypeExpr) + fn.AddComments(fmt.Sprintf("returns the %s property", strings.Join(d.propertyPath, "."))) + + return fn.DefineFunc(), nil +} diff --git a/v2/tools/generator/internal/testcases/json_serialization_test_case.go b/v2/tools/generator/internal/testcases/json_serialization_test_case.go index 83702cd50e2..af01281bf73 100644 --- a/v2/tools/generator/internal/testcases/json_serialization_test_case.go +++ b/v2/tools/generator/internal/testcases/json_serialization_test_case.go @@ -86,6 +86,9 @@ func (o *JSONSerializationTestCase) AsFuncs( // Remove properties from our runtime o.removeByPackage(properties, astmodel.GenRuntimeReference) + o.removeByPackage(properties, astmodel.GenRuntimeConfigMapsReference) + o.removeByPackage(properties, astmodel.GenRuntimeSecretsReference) + o.removeByPackage(properties, astmodel.GenRuntimeCoreReference) // Remove API machinery properties o.removeByPackage(properties, astmodel.APIMachineryRuntimeReference)